videofeeds/livetvutils/src/CIptvEpgDatabase.cpp
changeset 0 96612d01cf9f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/videofeeds/livetvutils/src/CIptvEpgDatabase.cpp	Mon Jan 18 20:21:12 2010 +0200
@@ -0,0 +1,3222 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:    Offers interface to IPTV Epg database*
+*/
+
+
+
+
+// INCLUDE FILES
+#include <badesca.h>    // CDesCArrayFlat
+#include <bautils.h>    // file helpers
+#include <d32dbms.h>
+#include <eikenv.h>
+#include "CIptvEpgLatestEpgAvailable.h"
+#include "IptvLiveLogger.h"
+
+#include "CIptvEpgDatabase.h"
+#include "CIptvEpgChannel.h"
+#include "CIptvEpgProgram.h"
+#include "CIptvEpgProgramWithSchedule.h"
+#include "CIptvEpgSchedule.h"
+#include "CIptvEpgScheduleSearch.h"
+
+// CONSTANTS
+
+// constant for program guide: day changes at 04:00 AM
+// Note: If you modify this, the range is 0-23, otherwise
+// USER 3 panic will happen in GetSchedulesByChannelAndDayL
+const TInt KIptvDefaultDayOffsetHours( 4 ); 
+const TInt KIptvDefaultUriCount( 5 );
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CIptvEpgDatabase::CIptvEpgDatabase
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+CIptvEpgDatabase::CIptvEpgDatabase( const TFileName& aDbFile ) : 
+	iDbFile( aDbFile ), iLocalState( EReady )
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CIptvEpgDatabase::ConstructL
+// Second phase construction. Leaves, if RFs session cannot be created.
+// -----------------------------------------------------------------------------
+void CIptvEpgDatabase::ConstructL()
+	{
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::ConstructL()"));
+    User::LeaveIfError( iFsSession.Connect() );
+    MakeSqlStrings();
+    
+    // Create database and connect into it
+	CreateDbL();
+
+	TRAPD( error, CreateMulticastDbSessionL());
+    if ( error != KErrNone )
+        {
+        LIVE_TV_TRACE2(_L("CIptvEpgDatabase:: Could not open session to db (%d)"), error);
+
+        if ( error != KErrNoMemory && 
+             error != KErrLocked && 
+             error != KErrDisMounted &&
+             error != KErrDiskFull &&
+             error != KErrNotReady )
+            {
+            // Delete and recreate database file. Cannot recover other way. 
+            LIVE_TV_TRACE1(_L("CIptvEpgDatabase:: fatal error occured while opening db, recreating db"));
+            
+            iFsSession.Delete( iDbFile ); //ignore error
+            
+            TRAP( error, CreateDbL() );
+            if ( error != KErrNone )
+                {
+                LIVE_TV_TRACE2(_L("CIptvEpgDatabase:: couldnt recreate db (%d), leaving."), error);
+                User::Leave( error );
+                }
+                
+            TRAP( error, CreateMulticastDbSessionL() );
+            if ( error != KErrNone )
+                {
+                LIVE_TV_TRACE2(_L("CIptvEpgDatabase:: couldnt open session to db (%d), leaving."), error);
+                User::Leave( error );
+                }
+                
+            }
+        else
+            {
+            LIVE_TV_TRACE1(_L("CIptvEpgDatabase:: temporary error occured while opening db, leaving db intact, leaving."));
+            User::Leave( error );
+            }
+        }
+	
+	iLocalState = EReady;
+	
+	// Register to listen the file for backup
+	iBackupWrapper = CBaBackupSessionWrapper::NewL();
+	iBackupWrapper->RegisterFileL( iDbFile, *this );
+	
+	iActiveWait = new (ELeave) CActiveSchedulerWait();
+    }
+
+// -----------------------------------------------------------------------------
+// CIptvEpgDatabase::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+EXPORT_C CIptvEpgDatabase* CIptvEpgDatabase::NewL(const TFileName& aDbFile)
+    {
+    LIVE_TV_TRACE1(_L("CIptvEpgDatabase::NewL()"));
+    CIptvEpgDatabase* self = new ( ELeave ) CIptvEpgDatabase( aDbFile );    
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );    
+    return self;
+    }
+    
+// -----------------------------------------------------------------------------
+// CIptvEpgDatabase::~CIptvEpgDatabase()
+// Destructor
+// -----------------------------------------------------------------------------
+CIptvEpgDatabase::~CIptvEpgDatabase()
+    {
+    LIVE_TV_TRACE1(_L("CIptvEpgDatabase::~CIptvEpgDatabase in"));
+	if ( iBackupWrapper )
+		{
+		iBackupWrapper->DeregisterFile( iDbFile );
+		}
+	delete iBackupWrapper;
+    iFsSession.Close();
+    CloseMulticastDbSession();
+    
+    if ( iActiveWait && iActiveWait->IsStarted() )
+    	{
+    	iActiveWait->AsyncStop();
+    	}
+    delete iActiveWait;
+    LIVE_TV_TRACE1(_L("CIptvEpgDatabase::~CIptvEpgDatabase out"));    
+    }
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::CreateDbL()
+//
+// Create a new database. 
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::CreateDbL()
+    {
+    LIVE_TV_TRACE1(_L("CIptvEpgDatabase::CreateDbL()"));
+    if ( !BaflUtils::FileExists( iFsSession, iDbFile ) )
+        {
+        LIVE_TV_TRACE1( _L("Database file wasn't found, creating new"));
+    	RDbNamedDatabase database;
+		CleanupClosePushL( database );
+		BaflUtils::EnsurePathExistsL( iFsSession, iDbFile );
+    	User::LeaveIfError( database.Create( iFsSession, iDbFile ) );
+        
+		CreateChannelTableL( database );
+        
+        CreateProgramTableL( database );
+        
+        CreateScheduleTableL( database );
+
+		CreateLatestEpgAvailableTableL( database );
+		
+		CreateLastModifiedTableL( database );
+
+        CleanupStack::PopAndDestroy( &database );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::CreateMulticastDbSessionL()
+//
+// Open a new database session and the database
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::CreateMulticastDbSessionL()
+    {
+    LIVE_TV_TRACE1(_L("CIptvEpgDatabase::CreateMulticastDbSessionL()"));
+    User::LeaveIfError( iMulticastDbSession.Connect() );
+    User::LeaveIfError( iMulticastDb.Open( iMulticastDbSession, iDbFile ) );
+    User::LeaveIfError( iMulticastDb.Compact() );
+    }
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::CloseMulticastDbSession()
+//
+// Closes a database session and the database
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::CloseMulticastDbSession()
+    {
+    LIVE_TV_TRACE1(_L("CIptvEpgDatabase::CloseMulticastDbSession()"));
+    iMulticastDb.Close();
+    iMulticastDbSession.Close();
+    }
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::CreateScheduleTableL()
+//
+// Creates schedule database table
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::CreateScheduleTableL( RDbNamedDatabase& aDatabase ) const
+	{
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::CreateScheduleTableL()"));
+	TDbCol keyCol( KIptvEpgScheduleTableKeyCol, EDbColUint32 );
+	keyCol.iAttributes = TDbCol::EAutoIncrement;
+	
+	TDbCol serviceIdCol( KIptvEpgScheduleServiceProviderIdCol, EDbColUint32 );
+	
+	TDbCol channelIdCol( KIptvEpgScheduleChannelIdCol, EDbColInt64 );
+	
+	TDbCol programIdCol( KIptvEpgScheduleProgramIdCol, EDbColInt64 );
+	
+	TDbCol startTimeCol( KIptvEpgScheduleStartTimeCol, EDbColDateTime );
+	
+	TDbCol endTimeCol( KIptvEpgScheduleEndTimeCol, EDbColDateTime );
+
+    CDbColSet* scheduleColSet = CDbColSet::NewLC();
+    scheduleColSet->AddL( keyCol );
+    scheduleColSet->AddL( serviceIdCol );
+    scheduleColSet->AddL( channelIdCol );
+    scheduleColSet->AddL( programIdCol );
+    scheduleColSet->AddL( startTimeCol );
+    scheduleColSet->AddL( endTimeCol );
+        
+    User::LeaveIfError( aDatabase.CreateTable( KIptvEpgScheduleTable, *scheduleColSet ) );
+    CleanupStack::PopAndDestroy( scheduleColSet );
+	}
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::CreateChannelProgramTableL()
+//
+// Creates ChannelProgram table. Leaves, if the table cannot be created.
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::CreateChannelProgramTableL( 
+										RDbNamedDatabase& /*aDatabase*/ ) const
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::CreateProgramTableL()
+//
+// Creates Program table. Leaves, if the table cannot be created.
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::CreateProgramTableL( RDbNamedDatabase& aDatabase ) const
+    {
+	LIVE_TV_TRACE1( _L("CIptvEpgDatabase::CreateProgramTableL" ) );
+    // Key  
+    TDbCol keyCol( KIptvEpgProgramDbKeyCol, EDbColUint32 );
+    keyCol.iAttributes = TDbCol::EAutoIncrement;
+    
+    TDbCol idCol( KIptvEpgProgramIdCol, EDbColInt64 );
+    
+    TDbCol channelIdCol( KIptvEpgProgramChannelId, EDbColInt64 );
+    
+	TDbCol servProvIdCol( KIptvEpgProgramServProviderIdCol, EDbColUint32 );
+    
+    TDbCol uriCol( KIptvEpgProgramURICol, EDbColText, KIptvEpgUriMaxLength );
+    
+    TDbCol genreCol( KIptvEpgProgramGenreCol, EDbColText );
+    
+    TDbCol nameCol( KIptvEpgProgramNameCol, EDbColText, KIptvEpgProgramMaxLength );
+    
+    TDbCol descriptionCol( KIptvEpgProgramDescriptionCol, EDbColLongText );
+    
+    TDbCol languageCol( KIptvEpgProgramLanguageCol, EDbColText );
+    
+    TDbCol parentalCol( KIptvEpgProgramParentalRatingCol, EDbColText );
+    
+    CDbColSet* programColSet = CDbColSet::NewLC();
+    programColSet->AddL( keyCol );
+    programColSet->AddL( idCol );
+    programColSet->AddL( channelIdCol );
+	programColSet->AddL( servProvIdCol );
+    programColSet->AddL( uriCol );
+    programColSet->AddL( genreCol );
+    programColSet->AddL( nameCol );
+    programColSet->AddL( descriptionCol );
+    programColSet->AddL( languageCol );
+    programColSet->AddL( parentalCol );
+        
+    TInt error = aDatabase.CreateTable( KIptvEpgProgramTable, 
+										*programColSet );
+    if ( error != KErrNone )
+        {
+        LIVE_TV_TRACE2( _L("\t\tCIptvEpgDatabase::CreateProgramTableL CreateTable returned %d"), error );
+        User::Leave( error );
+        }
+    
+    CleanupStack::PopAndDestroy( programColSet ); 
+    }
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::CreateChannelTableL()
+//
+// Creates Channel table. Leaves, if the table cannot be created.
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::CreateChannelTableL( RDbNamedDatabase& aDatabase ) const
+    {
+	LIVE_TV_TRACE1( _L("CIptvEpgDatabase::CreateChannelTableL" ) );
+    // Key    
+    TDbCol keyCol( KIptvEpgChannelDbKeyCol, EDbColUint32 );
+    keyCol.iAttributes = TDbCol::EAutoIncrement;
+
+    TDbCol idCol( KIptvEpgChannelIdCol, EDbColInt64 );
+    
+    TDbCol servProvIdCol( KIptvEpgChannelServProviderIdCol, EDbColUint32 );
+    
+    TDbCol nameCol( KIptvEpgChannelNameCol, EDbColText, KIptvEpgChannelNameMaxLength );
+    
+    TDbCol logoPathCol( KIptvEpgChannelLogoPathCol, EDbColText, KIptvEpgLogoPathMaxLength );
+    
+    TDbCol descriptionCol( KIptvEpgChannelDescriptionCol, EDbColText,
+                           KIptvEpgDescrMaxLength );
+    
+    TDbCol uriCol( KIptvEpgChannelURICol, EDbColText, KIptvEpgUriMaxLength );
+    
+    TDbCol sdpCol( KIptvEpgChannelSDPCol, EDbColLongText );
+
+	TDbCol orderCol( KIptvEpgChannelOrderCol, EDbColUint32 );
+
+	// Create column set and add defined columns in to the set
+    CDbColSet* channelColSet = CDbColSet::NewLC();
+    channelColSet->AddL( keyCol );
+    channelColSet->AddL( idCol );
+    channelColSet->AddL( servProvIdCol );
+    channelColSet->AddL( nameCol );
+    channelColSet->AddL( logoPathCol );
+    channelColSet->AddL( descriptionCol );
+    channelColSet->AddL( uriCol );
+    channelColSet->AddL( sdpCol );
+    channelColSet->AddL( orderCol );
+
+    // Create new table to the database with created columnset
+    TInt error = aDatabase.CreateTable( KIptvEpgChannelTable, 
+										*channelColSet );
+    if ( error != KErrNone )
+    	{
+    	LIVE_TV_TRACE2( _L("\n\t\tCIptvEpgDatabase::CreateChannelTableL: CreateTable returned %d" ), error );
+        User::Leave( error );
+        }
+    
+    CleanupStack::PopAndDestroy( channelColSet );
+    }
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::CreateLastModifiedTableL()
+//
+// Creates table for last modified data
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::CreateLastModifiedTableL( RDbNamedDatabase& aDatabase ) const
+	{
+	// First create columns
+	TDbCol keyCol( KIptvEpgLastModifiedTableKeyCol, EDbColUint32 );
+    keyCol.iAttributes = TDbCol::EAutoIncrement;
+    TDbCol serviceIdCol( KIptvEpgLastModifiedTableServiceIdCol, EDbColUint32 );
+	TDbCol eTagCol( KIptvEpgLastModifiedTableETagCol, EDbColText );
+	TDbCol lastModifiedDateTime( KIptvEpgLastModifiedTableTimeCol, EDbColText );
+	
+	CDbColSet* lastModifiedColSet = CDbColSet::NewLC();
+	lastModifiedColSet->AddL( keyCol );
+	lastModifiedColSet->AddL( serviceIdCol );
+	lastModifiedColSet->AddL( eTagCol );
+	lastModifiedColSet->AddL( lastModifiedDateTime );
+	
+	TInt error = aDatabase.CreateTable( KIptvEpgLastModifiedTable, *lastModifiedColSet );
+	
+	CleanupStack::PopAndDestroy( lastModifiedColSet );
+	
+	if ( error != KErrNone )
+		{
+		LIVE_TV_TRACE2( _L("aDatabase.CreateTable for last modified table caused leave: %d"), error );
+		User::Leave( error );
+		}
+	}
+
+
+// SET OF GETTERS FOR CHANNEL AND PROGRAM DATA
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::GetChannelsL()
+// 
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CIptvEpgDatabase::GetChannelsL( const TUint32 aServiceProviderId,
+											  RPointerArray<CIptvEpgChannel>*
+											  aResultArray )
+	{
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::GetChannelsL()"));    	
+
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+    if ( !aResultArray )
+        {
+        User::Leave( KErrArgument );
+        }
+	TBuf<KCustomSqlLength> sqlStatement;
+    sqlStatement.Append( _L("SELECT * FROM "));
+    sqlStatement.Append( KIptvEpgChannelTable );
+    sqlStatement.Append( _L(" WHERE ") );
+    sqlStatement.Append( KIptvEpgChannelServProviderIdCol );
+    sqlStatement.Append( _L(" = ") );
+    sqlStatement.AppendNum( aServiceProviderId );
+	DoGetChannelsL( sqlStatement, aResultArray );    
+    }
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::DoGetChannelsL()
+// 
+// ---------------------------------------------------------------------------
+//
+void CIptvEpgDatabase::DoGetChannelsL( const TDesC& aQuery,
+											  RPointerArray<CIptvEpgChannel>*
+											  aResultArray )
+	{
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::DoGetChannelsL() in"));
+
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	TInt err( KErrNone ); 
+	
+    if ( !aResultArray )
+        {
+        User::Leave( KErrArgument );
+        }
+    
+    RDbView view;
+    CleanupClosePushL( view );
+    LIVE_TV_TRACE1( _L("CIptvEpgDatabase::DoGetChannelsL about to prepare") ); 
+    err =  view.Prepare( iMulticastDb,
+    					 TDbQuery(aQuery),
+    					 TDbWindow::EUnlimited,
+    					 RDbView::EReadOnly );
+    LIVE_TV_TRACE2( _L("CIptvEpgDatabase::DoGetChannelsL  prepare = %d"), err ); 
+    User::LeaveIfError ( err ); 
+    LIVE_TV_TRACE1( _L("CIptvEpgDatabase::DoGetChannelsL about to eval") );        								  
+    User::LeaveIfError( view.EvaluateAll() );
+    LIVE_TV_TRACE1( _L("CIptvEpgDatabase::DoGetChannelsL about to get colset ") );        
+    CDbColSet* colSet = view.ColSetL();
+	CleanupStack::PushL( colSet );
+    TInt idColNo = colSet->ColNo( KIptvEpgChannelIdCol );
+    TInt servProbIdColNo = colSet->ColNo( KIptvEpgChannelServProviderIdCol );
+    TInt nameColNo = colSet->ColNo( KIptvEpgChannelNameCol );
+    TInt logoColNo = colSet->ColNo( KIptvEpgChannelLogoPathCol );
+    TInt descrColNo = colSet->ColNo( KIptvEpgChannelDescriptionCol );
+    TInt uriColNo = colSet->ColNo( KIptvEpgChannelURICol );
+    TInt sdpColNo = colSet->ColNo( KIptvEpgChannelSDPCol );
+	TInt orderColNo = colSet->ColNo( KIptvEpgChannelOrderCol );
+
+	CleanupStack::PopAndDestroy( colSet );
+    LIVE_TV_TRACE1( _L("CIptvEpgDatabase::DoGetChannelsL getting first") );        
+    view.FirstL();
+    while ( view.AtRow() )
+        {
+        view.GetL();            
+        CIptvEpgChannel* channel = CIptvEpgChannel::NewL();
+        CleanupStack::PushL( channel );
+
+		channel->SetChannelId( view.ColInt64( idColNo ) );
+		channel->SetServiceId( view.ColUint32( servProbIdColNo ) );
+		channel->SetChannelName( view.ColDes( nameColNo ).AllocL() );
+		channel->SetChannelLogoPath( view.ColDes( logoColNo ).AllocL() );
+		channel->SetChannelDescription( view.ColDes( descrColNo ).AllocL() );
+		channel->SetChannelURI( view.ColDes( uriColNo ).AllocL() );
+
+		// SDP data is stored in long text field, so it needs to be read
+		// through stream
+		TInt sdpLength = view.ColLength( sdpColNo );
+		HBufC* temp = HBufC::NewL( sdpLength );
+		CleanupStack::PushL( temp );
+		RDbColReadStream read;
+		read.OpenLC( view, sdpColNo );
+		TPtr ptr = temp->Des();
+		read.ReadL( ptr, sdpLength );
+		read.Close();
+		CleanupStack::PopAndDestroy(); // read;
+		channel->SetChannelSDP( temp ); // Ownership transferred
+		CleanupStack::Pop( temp );
+
+		channel->SetChannelOrder( view.ColUint32( orderColNo ) );
+		
+		TLinearOrder<CIptvEpgChannel> order(
+							CIptvEpgChannel::LinearOrderByOrderNum );
+		// Insert the channel to the array ordered by 
+		// CIptvEpgChannel::LinearOrderByOrderNum function
+		User::LeaveIfError( aResultArray->InsertInOrderAllowRepeats( channel,
+							order ) );
+        
+        CleanupStack::Pop( channel ); // ownership transferred to aResultArray
+        view.NextL();
+        }
+
+	LIVE_TV_TRACE2( _L("Added %d channels to aResultArray"), aResultArray->Count() );
+
+	CleanupStack::PopAndDestroy( &view ); // closes view
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::DoGetChannelsL() out"));
+    }
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::GetProgramsByChannelIdL()
+// 
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CIptvEpgDatabase::GetProgramsByChannelIdL( 
+								const TUint32 aServiceProviderId,
+								const TInt64 aChannelKey,
+								RPointerArray<CIptvEpgProgram>* aResultArray )
+    {
+    LIVE_TV_TRACE3(_L("CIptvEpgDatabase::GetProgramsByChannelIdL() ser %d cha %Li"), (int)aServiceProviderId, aChannelKey);
+
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	if ( !aResultArray )
+		{
+		User::Leave( KErrArgument );
+		}
+	TBuf<KCustomSqlLength> sqlStatement;
+	sqlStatement.Append( _L("SELECT * FROM ") );
+	sqlStatement.Append( KIptvEpgProgramTable );
+	sqlStatement.Append( _L(" WHERE ") );
+	sqlStatement.Append( KIptvEpgProgramChannelId );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aChannelKey );
+	sqlStatement.Append( _L(" AND ") );
+	sqlStatement.Append( KIptvEpgProgramServProviderIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aServiceProviderId );
+
+    LIVE_TV_TRACE2(_L("query >%S<"), &sqlStatement);
+    
+	FetchProgramsFromTableL( sqlStatement, aResultArray );
+	
+    }
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::GetNextProgramL()
+// 
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CIptvEpgSchedule* CIptvEpgDatabase::GetNextProgramL( 
+								const TUint32 aServiceProviderId,
+								const TInt64 aChannelKey,
+								const TTime& aRefTime )
+    {
+	LIVE_TV_TRACE3(_L("CIptvEpgDatabase::GetNextProgramL() ser %d cha %Li"), (int)aServiceProviderId, aChannelKey);
+
+	if ( iLocalState == EBackup )
+		{
+		return NULL;
+		}
+	
+	TBuf<KCustomSqlLength> sqlStatement;    
+    sqlStatement.Append( _L("SELECT * FROM ") );
+	sqlStatement.Append( KIptvEpgScheduleTable );
+	sqlStatement.Append( _L(" WHERE ") );
+	sqlStatement.Append( KIptvEpgScheduleChannelIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aChannelKey );
+	sqlStatement.Append( _L(" AND ") );
+	sqlStatement.Append( KIptvEpgScheduleServiceProviderIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aServiceProviderId );
+    LIVE_TV_TRACE2(_L("query >%S<"), &sqlStatement);
+
+    CIptvEpgSchedule* retval = NULL;
+	
+	RPointerArray<CIptvEpgSchedule> resultArray;
+	CleanupClosePushL( resultArray );
+	TRAPD( err, FetchSchedulesFromTableL( sqlStatement, &resultArray ) );
+	if ( err != KErrNone )
+		{
+		LIVE_TV_TRACE2(_L("CIptvEpgDatabase::GetNextProgramL: FetchSchedulesFromTableL FAILED: %d"), err);
+		resultArray.ResetAndDestroy();
+		User::Leave( err );
+		}
+	
+	const TInt cnt( resultArray.Count() );
+	TInt index( KErrNotFound );
+	for ( TInt i( 0 ); i < cnt; i++ )
+	    {
+	    // quit looping when the 1st prg which starting time is greater
+	    // than current time
+	    if ( resultArray[i]->GetStartTime() > aRefTime )
+	        {
+	        retval = resultArray[i];
+	        index = i;
+	        i = cnt; // quit looping
+	        }
+	    }
+	
+	if ( cnt > 0 )
+		{
+		for ( TInt j( 0 ); j < cnt; j++ ) // note, starts from 1, not 0. 
+			{
+			if ( j != index )
+			    {
+    			delete resultArray[j]; 
+    			resultArray[j] = NULL;
+			    }
+			}
+		
+		if ( index < 0 )
+		    {
+		    resultArray.Reset();
+	        CleanupStack::PopAndDestroy( &resultArray ); // closes array	
+	        return retval;
+		    }
+		if ( retval )
+			{
+			// match the found schedule with correct program data, query program table
+			TBuf<KCustomSqlLength> sqlStatementForPrograms;
+			sqlStatementForPrograms.Append( _L("SELECT * FROM ") );
+			sqlStatementForPrograms.Append( KIptvEpgProgramTable );
+			sqlStatementForPrograms.Append( _L(" WHERE ") );
+			sqlStatementForPrograms.Append( KIptvEpgProgramChannelId );
+			sqlStatementForPrograms.Append( _L(" = ") );
+			sqlStatementForPrograms.AppendNum( aChannelKey );
+			sqlStatementForPrograms.Append( _L(" AND ") );
+			sqlStatementForPrograms.Append( KIptvEpgProgramServProviderIdCol );
+			sqlStatementForPrograms.Append( _L(" = ") );
+			sqlStatementForPrograms.AppendNum( aServiceProviderId );
+			sqlStatementForPrograms.Append( _L(" AND ") );
+			sqlStatementForPrograms.Append( KIptvEpgProgramIdCol );
+			sqlStatementForPrograms.Append( _L(" = ") );
+			sqlStatementForPrograms.AppendNum( retval->GetProgramId() );
+			
+			RPointerArray<CIptvEpgProgram> resultProgArray;
+			CleanupClosePushL( resultProgArray );
+		    
+			TRAP( err, FetchProgramsFromTableL( sqlStatementForPrograms, 
+				  &resultProgArray ) );
+			if ( err != KErrNone )
+				{
+				LIVE_TV_TRACE2(_L("FetchProgramsFromTableL FAILED: %d"), err);
+				resultArray.ResetAndDestroy();
+				resultProgArray.ResetAndDestroy();
+				User::Leave( err );
+				}
+
+			const TInt cntProg( resultProgArray.Count() );
+			if ( cntProg > 0 )
+				{
+				retval->iProgram = resultProgArray[0];// note, index 0 is the matching prog
+				for ( TInt k( 1 ); k < cntProg; k++ ) // note, starts from 1, not 0. 
+					{
+					delete resultProgArray[k]; 
+					resultProgArray[k] = NULL;
+					}
+				}
+			else
+				{
+				// no matching program found	
+				}
+			resultProgArray.Reset();			
+			CleanupStack::PopAndDestroy( &resultProgArray ); // closes array					
+			}	
+		}
+		
+    	    
+	resultArray.Reset();
+	CleanupStack::PopAndDestroy( &resultArray ); // closes array	
+	return retval;
+    }
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::GetProgramL()
+// 
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CIptvEpgSchedule* CIptvEpgDatabase::GetProgramL( 
+								const TUint32 aServiceProviderId,
+								const TInt64 aChannelId,
+								const TInt64 aProgramId )
+    {
+	LIVE_TV_TRACE4(_L("CIptvEpgDatabase::GetProgramL() in aServiceProviderId %d aChannelId %Li, aProgramId %Li"), (int)aServiceProviderId, aChannelId, aProgramId);
+
+	if ( iLocalState == EBackup )
+		{
+		return NULL;
+		}
+	
+	TBuf<KCustomSqlLength> sqlStatement;    
+    sqlStatement.Append( _L("SELECT * FROM ") );
+	sqlStatement.Append( KIptvEpgScheduleTable );
+	sqlStatement.Append( _L(" WHERE ") );
+	sqlStatement.Append( KIptvEpgScheduleChannelIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aChannelId );
+	sqlStatement.Append( _L(" AND ") );
+	sqlStatement.Append( KIptvEpgScheduleServiceProviderIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aServiceProviderId );
+	sqlStatement.Append( _L(" AND ") );
+	sqlStatement.Append( KIptvEpgScheduleProgramIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aProgramId );
+	
+    CIptvEpgSchedule* retval = NULL;
+	
+	RPointerArray<CIptvEpgSchedule> resultArray;
+	CleanupClosePushL( resultArray );
+	TRAPD( err, FetchSchedulesFromTableL( sqlStatement, &resultArray ) );
+	if ( err != KErrNone )
+		{
+		LIVE_TV_TRACE2(_L("FetchSchedulesFromTableL FAILED: %d"), err);
+		resultArray.ResetAndDestroy();
+		User::Leave( err );
+		}
+		
+	if ( resultArray.Count() > 0 )
+		{
+		// Select first one found
+		retval = resultArray[0];
+		resultArray.Remove( 0 );
+		}
+	resultArray.ResetAndDestroy();
+	CleanupStack::PopAndDestroy( &resultArray );
+
+	TBuf<KCustomSqlLength> sqlStatementForPrograms;
+	sqlStatementForPrograms.Append( _L("SELECT * FROM ") );
+	sqlStatementForPrograms.Append( KIptvEpgProgramTable );
+	sqlStatementForPrograms.Append( _L(" WHERE ") );
+	sqlStatementForPrograms.Append( KIptvEpgProgramChannelId );
+	sqlStatementForPrograms.Append( _L(" = ") );
+	sqlStatementForPrograms.AppendNum( aChannelId );
+	sqlStatementForPrograms.Append( _L(" AND ") );
+	sqlStatementForPrograms.Append( KIptvEpgProgramServProviderIdCol );
+	sqlStatementForPrograms.Append( _L(" = ") );
+	sqlStatementForPrograms.AppendNum( aServiceProviderId );
+	sqlStatementForPrograms.Append( _L(" AND ") );
+	sqlStatementForPrograms.Append( KIptvEpgProgramIdCol );
+	sqlStatementForPrograms.Append( _L(" = ") );
+	sqlStatementForPrograms.AppendNum( aProgramId );
+	
+	RPointerArray<CIptvEpgProgram> resultProgArray;
+	CleanupClosePushL( resultProgArray );
+	    
+	TRAP( err, FetchProgramsFromTableL( sqlStatementForPrograms, 
+		  &resultProgArray ) );
+	if ( err != KErrNone )
+		{
+		LIVE_TV_TRACE2(_L("FetchProgramsFromTableL FAILED: %d"), err);
+		resultProgArray.ResetAndDestroy();
+		User::Leave( err );
+		}
+	if ( resultProgArray.Count() > 0 && retval )
+		{
+		retval->iProgram = resultProgArray[0];
+		resultProgArray.Remove( 0 );
+		}
+	resultProgArray.ResetAndDestroy();	
+	CleanupStack::PopAndDestroy( &resultProgArray ); // closes array					
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::GetProgramL out"));
+	return retval;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::GetProgramNamesByServiceIdL()
+// 
+// ---------------------------------------------------------------------------
+//
+void CIptvEpgDatabase::GetProgramNamesByServiceIdL( 
+								const TUint32 aServiceProviderId,
+								RPointerArray<CIptvEpgProgram>* aResultArray )
+    {
+    LIVE_TV_TRACE2(_L("CIptvEpgDatabase::GetProgramsByServiceIdL() ser %d"), (TInt)aServiceProviderId);
+
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	if ( !aResultArray )
+		{
+		User::Leave( KErrArgument );
+		}
+	TBuf<KCustomSqlLength> sqlStatement;
+	sqlStatement.Append( _L("SELECT ") );
+	sqlStatement.Append( KIptvEpgProgramIdCol );
+	sqlStatement.Append( _L(", ") );
+	sqlStatement.Append( KIptvEpgProgramNameCol );
+	sqlStatement.Append( _L(" FROM "));
+	sqlStatement.Append( KIptvEpgProgramTable );
+	sqlStatement.Append( _L(" WHERE ") );
+	sqlStatement.Append( KIptvEpgProgramServProviderIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aServiceProviderId );
+
+    LIVE_TV_TRACE2(_L("query >%S<"), &sqlStatement);
+    
+	FetchProgramNamesFromTableL( sqlStatement, aResultArray );
+	
+    }
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::GetSchedulesByServiceIdL()
+// 
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CIptvEpgDatabase::GetSchedulesByServiceIdL( 
+						const TUint32 aServiceProviderId,
+						RPointerArray<CIptvEpgScheduleSearch>* aResultArray )
+    {
+    LIVE_TV_TRACE2(_L("CIptvEpgDatabase::GetSchedulesByServiceIdL() ser %d"), (TInt)aServiceProviderId);
+
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	if ( !aResultArray )
+		{
+		User::Leave( KErrArgument );
+		}
+		
+	CIptvEpgProgram* programToUseForFinding = CIptvEpgProgram::NewL(); 
+	CleanupStack::PushL( programToUseForFinding ); 
+    
+	RPointerArray<CIptvEpgProgram> programs;
+	CleanupClosePushL( programs );
+	TRAPD( err, GetProgramNamesByServiceIdL( aServiceProviderId, &programs ) );
+	if ( err != KErrNone )
+		{
+		LIVE_TV_TRACE2(_L("GetProgramNamesByServiceIdL FAILED: %d"), err);
+		programs.ResetAndDestroy();
+		User::Leave( err );
+		}
+    TLinearOrder<CIptvEpgProgram> o( 
+							CIptvEpgProgram::LinearOrderOfProgramsById );
+	programs.Sort( o ); 
+    
+	TBuf<KCustomSqlLength> sqlStatement;
+	sqlStatement.Append( _L("SELECT * FROM ") );
+	sqlStatement.Append( KIptvEpgScheduleTable );
+	sqlStatement.Append( _L(" WHERE ") );
+	sqlStatement.Append( KIptvEpgScheduleServiceProviderIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aServiceProviderId );
+    LIVE_TV_TRACE2(_L("query >%S<"), &sqlStatement);
+    
+	TRAP( err, FetchSearchSchedulesFromTableL( sqlStatement, aResultArray ) );
+	if ( err != KErrNone )
+		{
+		LIVE_TV_TRACE2(_L("FetchSearchSchedulesFromTableL FAILED: %d"), err);
+		programs.ResetAndDestroy();
+		User::Leave( err );
+		}
+	
+	TInt indexFound( KErrNone ); 
+	TInt i( 0 );
+	TInt64 programId( 0 );
+	for ( i = 0; i < aResultArray->Count(); i++ ) 
+		{
+		programId = ((*aResultArray)[i])->iProgramId;
+		programToUseForFinding->SetProgramId( programId );
+		indexFound = programs.FindInOrder( programToUseForFinding, o ); 
+		if ( indexFound != KErrNotFound && indexFound < programs.Count() ) 
+			{
+			((*aResultArray)[i])->iProgramName = 
+						programs[indexFound]->ProgramName().AllocL();	
+			}
+		}
+
+	TLinearOrder<CIptvEpgScheduleSearch> order( 
+						CIptvEpgScheduleSearch::LinearOrderOfSchedulesByName );
+	aResultArray->Sort( order );
+
+	for ( i = 0; i < programs.Count(); i++ )
+		{
+		delete programs[i];
+		programs[i] = NULL;
+		}
+	programs.Reset();
+	CleanupStack::PopAndDestroy( &programs );
+	CleanupStack::PopAndDestroy( programToUseForFinding );
+	LIVE_TV_TRACE2(_L("CIptvEpgDatabase::GetSchedulesByServiceIdL out, return %d items"), aResultArray->Count() );	
+    }
+    
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::GetSchedulesByChannelIdL()
+// 
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CIptvEpgDatabase::GetSchedulesByChannelIdL( 
+								const TUint32 aServiceProviderId,
+								const TInt64 aChannelKey,
+								RPointerArray<CIptvEpgSchedule>* aResultArray )
+    {
+    LIVE_TV_TRACE3(_L("CIptvEpgDatabase::GetSchedulesByChannelIdL() ser %d cha %Li"), (int)aServiceProviderId, aChannelKey);
+
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	if ( !aResultArray )
+		{
+		User::Leave( KErrArgument );
+		}
+		
+	TInt i,c; 
+	CIptvEpgProgram* programToUseForFinding = CIptvEpgProgram::NewL(); 
+	CleanupStack::PushL(programToUseForFinding); 
+    LIVE_TV_TRACE1(_L("GetSchedulesByChannelIdL starting get prog"));
+	RPointerArray<CIptvEpgProgram> programs;
+	CleanupClosePushL( programs );
+    TRAPD( err, GetProgramsByChannelIdL(aServiceProviderId,	aChannelKey, &programs ) );
+	if ( err != KErrNone )
+		{
+		LIVE_TV_TRACE2(_L("GetProgramsByChannelIdL FAILED: %d"), err);
+		programs.ResetAndDestroy();
+		User::Leave( err );
+		}
+    LIVE_TV_TRACE2(_L("GetSchedulesByChannelIdL starting sort n = %d"),programs.Count());
+    TLinearOrder<CIptvEpgProgram> o(CIptvEpgProgram::LinearOrderOfProgramsById); 
+	programs.Sort( o );
+    LIVE_TV_TRACE1(_L("GetSchedulesByChannelIdL starting fetch schedules"));
+
+	TBuf<KCustomSqlLength> sqlStatement;
+	sqlStatement.Append( _L("SELECT * FROM ") );
+	sqlStatement.Append( KIptvEpgScheduleTable );
+	sqlStatement.Append( _L(" WHERE ") );
+	sqlStatement.Append( KIptvEpgScheduleChannelIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aChannelKey );
+	sqlStatement.Append( _L(" AND ") );
+	sqlStatement.Append( KIptvEpgScheduleServiceProviderIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aServiceProviderId );
+    LIVE_TV_TRACE2(_L("query >%S<"), &sqlStatement);
+    
+	TRAP( err, FetchSchedulesFromTableL( sqlStatement, aResultArray ) );
+	if ( err != KErrNone )
+		{
+		LIVE_TV_TRACE2(_L("FetchSchedulesFromTableL FAILED: %d"), err);
+		programs.ResetAndDestroy();
+		User::Leave( err );
+		}
+	TLinearOrder<CIptvEpgSchedule> order(CIptvEpgSchedule::LinearOrderOfSchedulesByTime); 
+	aResultArray->Sort(order); 
+	c = aResultArray->Count(); 	
+	TInt indexFound; 
+	TInt programsFound = 0;
+	LIVE_TV_TRACE2(_L("GetSchedulesByChannelIdL staring finding programs for %d schedules"),c);
+	TInt64 programId( 0 );
+	for ( i = 0; i < c; i ++ ) 
+		{
+		programId = ((*aResultArray)[i])->GetProgramId();
+		programToUseForFinding->SetProgramId( programId );
+		indexFound = programs.FindInOrder( programToUseForFinding, o ); 
+		if ( indexFound != KErrNotFound && indexFound < programs.Count() ) 
+			{
+			if ( programs[indexFound]->ServiceId() == aServiceProviderId &&
+				 programs[indexFound]->ChannelId() == aChannelKey )
+				{
+				((*aResultArray)[i])->iProgram = programs[indexFound];
+				programs.Remove( indexFound );
+				programsFound++; 	
+				}
+			}
+		}
+	programs.ResetAndDestroy();
+	CleanupStack::PopAndDestroy( &programs );
+	CleanupStack::PopAndDestroy( programToUseForFinding );
+	LIVE_TV_TRACE2(_L("GetSchedulesByChannelIdL matched %d programs "),programsFound);	
+    }
+    
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::GetSchedulesByChannelAndDayL()
+// 
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CIptvEpgDatabase::GetSchedulesByChannelAndDayL( 
+								const TUint32 aServiceProviderId,
+								const TInt64 aChannelKey,
+								const TTime& aStartTime,
+								RPointerArray<CIptvEpgSchedule>* aResultArray )
+    {
+    LIVE_TV_TRACE3(_L("CIptvEpgDatabase::GetSchedulesByChannelIdL() ser %d cha %Li"), (int)aServiceProviderId, aChannelKey);
+
+    if ( iLocalState == EBackup )
+        {
+        return;
+        }
+	
+    if ( !aResultArray )
+        {
+        User::Leave( KErrArgument );
+        }
+    // Assume aStartTime is set to HomeTime() (+ possible day offset)
+    TTime startTime( aStartTime );
+    
+    // fix for error JAIA-7FAF4U: if clock is less than 4 AM, 
+    // we're showing still the previous day's programs
+    startTime -= TTimeIntervalHours( KIptvDefaultDayOffsetHours );
+    TTime endTime( startTime );
+    // For some reason we need to set endTime to two days from home time to get 
+    // programs of tommorow from database
+    endTime += TTimeIntervalDays( 2 );
+    
+    startTime -= TTimeIntervalDays( 1 );
+    TDateTime startDateTime( startTime.DateTime() );
+    startDateTime.SetHour( 0 );
+    startDateTime.SetMinute( 0 );
+    startDateTime.SetSecond( 0 );
+    startDateTime.SetMicroSecond( 0 );
+    startTime = startDateTime;
+    startTime += TTimeIntervalHours( KIptvDefaultDayOffsetHours );
+
+    TBuf<100> startTimeBuf;
+    	
+    _LIT( KDateTimeFormat,"#%1%/1%2%/2%3#" ); 
+    startTime.FormatL(startTimeBuf, KDateTimeFormat); 
+     
+    TBuf<100> endTimeBuf;
+
+    endTime.FormatL(endTimeBuf, KDateTimeFormat);  
+    	
+    TInt i,c; 
+    CIptvEpgProgram* programToUseForFinding = CIptvEpgProgram::NewL(); 
+    CleanupStack::PushL(programToUseForFinding); 
+
+    RPointerArray<CIptvEpgProgram> programs;
+    CleanupClosePushL( programs );
+    LIVE_TV_TRACE1(_L("GetSchedulesByChannelIdL starting get prog"));
+    TRAPD( err, GetProgramsByChannelIdL( aServiceProviderId, aChannelKey, &programs ) );
+    if ( err != KErrNone )
+        {
+        LIVE_TV_TRACE2(_L("CIptvEpgDatabase::GetSchedulesByChannelAndDayL GetProgramsByChannelIdL FAILED: %d"), err);
+        programs.ResetAndDestroy();
+        User::Leave( err );
+        }
+
+    TLinearOrder<CIptvEpgProgram> o(CIptvEpgProgram::LinearOrderOfProgramsById); 
+    programs.Sort( o ); 
+    LIVE_TV_TRACE1(_L("GetSchedulesByChannelIdL starting fetch schedules"));
+    TBuf<KCustomSqlLength> sqlStatement;
+    sqlStatement.Append( _L("SELECT * FROM ") );
+    sqlStatement.Append( KIptvEpgScheduleTable );
+    sqlStatement.Append( _L(" WHERE ") );
+    sqlStatement.Append( KIptvEpgScheduleChannelIdCol );
+    sqlStatement.Append( _L(" = ") );
+    sqlStatement.AppendNum( aChannelKey );
+    sqlStatement.Append( _L(" AND ") );
+    sqlStatement.Append( KIptvEpgScheduleServiceProviderIdCol );
+    sqlStatement.Append( _L(" = ") );
+    sqlStatement.AppendNum( aServiceProviderId );
+    sqlStatement.Append( _L(" AND ") );
+    sqlStatement.Append( KIptvEpgScheduleStartTimeCol );
+    sqlStatement.Append( _L(" >= ") );
+    sqlStatement.Append( startTimeBuf );
+    sqlStatement.Append( _L(" AND ") );
+    sqlStatement.Append( KIptvEpgScheduleStartTimeCol );
+    sqlStatement.Append( _L(" <= ") );
+    sqlStatement.Append( endTimeBuf );
+
+    LIVE_TV_TRACE2(_L("query >%S<"), &sqlStatement);
+
+    TRAP( err, FetchSchedulesFromTableL( sqlStatement, aResultArray ) );
+    if ( err != KErrNone )
+        {
+        LIVE_TV_TRACE2(_L("CIptvEpgDatabase::GetSchedulesByChannelAndDayL: FetchSchedulesFromTableL FAILED: %d"), err);
+        programs.ResetAndDestroy();
+        User::Leave( err );
+        }
+    TTime progStartTime;
+    TTime progEndTime;
+    // Remove schedules from aResultArray that do not belong for today
+    // taking hour offset into account (e.g. when the day changes)
+    if ( aResultArray->Count() > 0 )
+        {
+        TTime endT( endTime - TTimeIntervalDays( 1 ) );
+        TDateTime endTDate = endT.DateTime();
+        endTDate.SetHour( KIptvDefaultDayOffsetHours );
+        endTDate.SetMinute( 0 );
+        endTDate.SetSecond( 0 );
+        endTDate.SetMicroSecond( 0 );
+        endT = endTDate;
+        const TTime startT( startTime + TTimeIntervalDays( 1 ) );
+        for ( i = aResultArray->Count() - 1; i >= 0; i-- )
+            {
+            progStartTime = (*aResultArray)[i]->GetStartTime() + 
+                User::UTCOffset();
+            progEndTime = (*aResultArray)[i]->GetEndTime() + User::UTCOffset();
+            
+            if ( progStartTime >= endT )
+                {
+                delete (*aResultArray)[i];
+                (*aResultArray)[i] = NULL;
+                aResultArray->Remove( i );    
+                }
+            else if ( progStartTime < startT && progEndTime <= startT )
+                {
+                delete (*aResultArray)[i];
+                (*aResultArray)[i] = NULL;
+                aResultArray->Remove( i );
+                }
+            }    
+        aResultArray->Compress();
+        }
+
+    TLinearOrder<CIptvEpgSchedule> order( CIptvEpgSchedule::LinearOrderOfSchedulesByTime ); 
+    aResultArray->Sort( order );
+    c = aResultArray->Count(); 	
+    TInt indexFound; 
+    TInt programsFound = 0;
+    LIVE_TV_TRACE2(_L("GetSchedulesByChannelIdL starting to find programs for %d schedules"),c);
+    TInt64 programId( 0 );
+    for ( i = 0; i < c; i ++ ) 
+    	{
+    	programId = ((*aResultArray)[i])->GetProgramId();
+    	programToUseForFinding->SetProgramId( programId );
+    	indexFound = programs.FindInOrder( programToUseForFinding, o ); 
+    	if ( indexFound != KErrNotFound ) 
+    		{
+    		((*aResultArray)[i])->iProgram = programs[indexFound];    
+    		programs.Remove( indexFound );
+    		programsFound ++; 
+    		}
+    	else
+    		{
+    		LIVE_TV_TRACE1(_L("Program not found in iProgramsPointedBySchedules!"));
+    		}
+    	}
+    programs.ResetAndDestroy();
+    CleanupStack::PopAndDestroy( &programs );
+    CleanupStack::PopAndDestroy( programToUseForFinding ); 	
+    LIVE_TV_TRACE2(_L("GetSchedulesByChannelIdL matched %d programs "),programsFound);	
+    } 
+
+// -----------------------------------------------------------------------------
+// CIptvEpgDatabase::GetProgramByTimeL()
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CIptvEpgSchedule* CIptvEpgDatabase::GetProgramByTimeL(
+												  const TUint32 aServiceProviderId, 
+												  const TInt64 aChannelKey,
+												  const TTime& aStartTime )
+	{
+	LIVE_TV_TRACE3(_L("CIptvEpgDatabase::GetProgramByTimeL() ser %d cha %Li"), (TInt)aServiceProviderId, aChannelKey);
+
+	if ( iLocalState == EBackup )
+		{
+		return NULL;
+		}
+	
+	CIptvEpgSchedule* retval = NULL;
+		
+	TBuf<100> startTimeBuf;
+	
+	// If date separator is set to ':' then the database will
+	// return KErrArgument (for some reason) if we use ':' also 
+	// as time separator.
+	// Avoid the error by selecting time format based on current
+	// date separator locale setting.
+	TLocale locale;
+	TChar dateSeparator = locale.DateSeparator( 1 );	
+	_LIT( KDateTimeFormatDoubleDot,"#%1%/1%2%/2%3 %H:%T:%S#" ); 
+	_LIT( KDateTimeFormatSingleDot,"#%1%/1%2%/2%3 %H.%T.%S#" ); 
+	TBuf<64> dateTimeFormat;
+	if ( dateSeparator == ':' )
+		{
+		dateTimeFormat = KDateTimeFormatSingleDot();
+		}
+	else
+		{
+		dateTimeFormat = KDateTimeFormatDoubleDot();
+		}
+	
+	aStartTime.FormatL(startTimeBuf, dateTimeFormat);  
+
+	// query the schedules table for the correct schedule
+	// that covers the given time in its duration			
+	TBuf<KCustomSqlLength> sqlStatement;
+	sqlStatement.Append( _L("SELECT * FROM ") );
+	sqlStatement.Append( KIptvEpgScheduleTable );
+	sqlStatement.Append( _L(" WHERE ") );
+	sqlStatement.Append( KIptvEpgScheduleChannelIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aChannelKey );
+	sqlStatement.Append( _L(" AND ") );
+	sqlStatement.Append( KIptvEpgScheduleServiceProviderIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aServiceProviderId );
+	sqlStatement.Append( _L(" AND ") );
+	sqlStatement.Append( KIptvEpgScheduleStartTimeCol );
+	sqlStatement.Append( _L(" <= ") );
+	sqlStatement.Append( startTimeBuf );
+	sqlStatement.Append( _L(" AND ") );
+	sqlStatement.Append( KIptvEpgScheduleEndTimeCol );
+	sqlStatement.Append( _L(" > ") );
+	sqlStatement.Append( startTimeBuf );
+	LIVE_TV_TRACE2(_L("query >%S<"), &sqlStatement);
+    
+    RPointerArray<CIptvEpgSchedule> resultArray;
+	CleanupClosePushL( resultArray );
+    TRAPD( err, FetchSchedulesFromTableL( sqlStatement, &resultArray ) );
+	if ( err != KErrNone )
+		{
+		LIVE_TV_TRACE2(_L("FetchSchedulesFromTableL FAILED: %d"), err);
+		resultArray.ResetAndDestroy();
+		User::Leave( err );
+		}
+		
+	const TInt cnt( resultArray.Count() );
+	
+	if ( cnt > 0 )
+		{
+		retval = resultArray[0];        // note, index 0 is the retval, not deleted
+		for ( TInt j( 1 ); j < cnt; j++ ) // note, starts from 1, not 0. 
+			{
+			delete resultArray[j]; 
+			resultArray[j] = NULL;
+			}
+		// match the found schedule with correct program data, query program table
+		TBuf<KCustomSqlLength> sqlStatementForPrograms;
+		sqlStatementForPrograms.Append( _L("SELECT * FROM ") );
+		sqlStatementForPrograms.Append( KIptvEpgProgramTable );
+		sqlStatementForPrograms.Append( _L(" WHERE ") );
+		sqlStatementForPrograms.Append( KIptvEpgProgramChannelId );
+		sqlStatementForPrograms.Append( _L(" = ") );
+		sqlStatementForPrograms.AppendNum( aChannelKey );
+		sqlStatementForPrograms.Append( _L(" AND ") );
+		sqlStatementForPrograms.Append( KIptvEpgProgramServProviderIdCol );
+		sqlStatementForPrograms.Append( _L(" = ") );
+		sqlStatementForPrograms.AppendNum( aServiceProviderId );
+		sqlStatementForPrograms.Append( _L(" AND ") );
+		sqlStatementForPrograms.Append( KIptvEpgProgramIdCol );
+		sqlStatementForPrograms.Append( _L(" = ") );
+		sqlStatementForPrograms.AppendNum( retval->GetProgramId() );
+		
+		RPointerArray<CIptvEpgProgram> resultProgArray;
+		CleanupClosePushL( resultProgArray );
+	    
+		TRAP( err, FetchProgramsFromTableL( sqlStatementForPrograms, 
+			  &resultProgArray ) );
+		if ( err != KErrNone )
+			{
+			LIVE_TV_TRACE2(_L("FetchProgramsFromTableL FAILED: %d"), err);
+			resultArray.ResetAndDestroy();
+			resultProgArray.ResetAndDestroy();
+			User::Leave( err );
+			}
+
+		const TInt cntProg( resultProgArray.Count() );
+	
+		if ( cntProg > 0 )
+			{
+			
+			retval->iProgram = resultProgArray[0];// note, index 0 is the matching prog
+			for ( TInt k( 1 ); k < cntProg; k++ ) // note, starts from 1, not 0. 
+				{
+				delete resultProgArray[k]; 
+				resultProgArray[k] = NULL;
+				}
+			}
+		else
+			{
+			// no matching program found	
+			}
+		resultProgArray.Reset();			
+		CleanupStack::PopAndDestroy( &resultProgArray ); // closes array					
+		}
+	else
+	    {
+	    // no schedule found for the given time	
+	    }
+	resultArray.Reset();
+	CleanupStack::PopAndDestroy( &resultArray ); // closes array   		
+	return retval;
+	}
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::FetchProgramsFromTableL()
+//
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::FetchProgramsFromTableL( const TDesC& aSqlStatement,
+							RPointerArray<CIptvEpgProgram>* aResultArray )
+	{
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::FetchProgramsFromTableL in"));
+
+	if ( iLocalState == EBackup || !aResultArray )
+		{
+		return;
+		}
+	
+	RDbView view;
+	CleanupClosePushL( view );
+
+	User::LeaveIfError( view.Prepare( iMulticastDb, 
+									   TDbQuery( aSqlStatement ) ) );
+	User::LeaveIfError( view.EvaluateAll() );
+	
+	CDbColSet* colSet = view.ColSetL();
+	CleanupStack::PushL( colSet );
+	TInt programIdColNo = colSet->ColNo( KIptvEpgProgramIdCol );
+	TInt channelIdColNo = colSet->ColNo( KIptvEpgProgramChannelId );
+	TInt serviceIdColNo = colSet->ColNo( KIptvEpgProgramServProviderIdCol );
+	TInt uriColNo = colSet->ColNo( KIptvEpgProgramURICol );
+	TInt genreColNo = colSet->ColNo( KIptvEpgProgramGenreCol );
+	TInt nameColNo = colSet->ColNo( KIptvEpgProgramNameCol );
+	TInt descrColNo = colSet->ColNo( KIptvEpgProgramDescriptionCol );
+	TInt languageColNo = colSet->ColNo( KIptvEpgProgramLanguageCol );
+	TInt parentalColNo = colSet->ColNo( KIptvEpgProgramParentalRatingCol );
+	CleanupStack::PopAndDestroy( colSet );
+	
+	view.FirstL();
+	while ( view.AtRow() )
+		{
+		view.GetL();
+		CIptvEpgProgram* program = CIptvEpgProgram::NewL();
+		CleanupStack::PushL( program );
+		program->SetProgramId( view.ColInt64( programIdColNo ) );
+		program->SetChannelId( view.ColInt64( channelIdColNo ) );
+		program->SetServiceId( view.ColUint32( serviceIdColNo ) );
+		program->SetProgramURI (view.ColDes( uriColNo ).AllocL() );
+		program->SetProgramGenre( view.ColDes( genreColNo ).AllocL() );
+		program->SetProgramName( view.ColDes( nameColNo ).AllocL() );
+		program->SetProgramLanguage( view.ColDes( languageColNo ).AllocL() );
+		program->SetProgramParentalRating( view.ColDes( parentalColNo ).AllocL() );
+		
+		// Description data is stored in long text field, so it needs to be read
+		// through stream
+		TInt descrLength = view.ColLength( descrColNo );
+		HBufC* temp = HBufC::NewL( descrLength );
+		CleanupStack::PushL( temp );
+		RDbColReadStream read;
+		read.OpenLC( view, descrColNo );
+		TPtr ptr = temp->Des();
+		read.ReadL( ptr, descrLength );
+		read.Close();
+		CleanupStack::PopAndDestroy(); // read;
+
+		program->SetProgramDescription( temp ); // Ownership transferred
+		CleanupStack::Pop( temp );
+
+		// Since now ownership of CIptvEpgProgram object is in RPointerArray	
+		aResultArray->AppendL( program );
+		
+		CleanupStack::Pop( program );
+		
+		view.NextL();
+		}
+	CleanupStack::PopAndDestroy( &view ); // closes view
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::FetchProgramsFromTableL out"));
+	}
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::FetchProgramNamesFromTableL()
+//
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::FetchProgramNamesFromTableL( const TDesC& aSqlStatement,
+							RPointerArray<CIptvEpgProgram>* aResultArray )
+	{
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::FetchProgramNamesFromTableL in"));
+
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	if ( !aResultArray ) 
+		{
+		User::Leave( KErrArgument );
+		}
+	RDbView view;
+	CleanupClosePushL( view );
+
+	User::LeaveIfError( view.Prepare( iMulticastDb, 
+									   TDbQuery( aSqlStatement ) ) );
+	User::LeaveIfError( view.EvaluateAll() );
+	
+	CDbColSet* colSet = view.ColSetL();
+	CleanupStack::PushL( colSet );
+	TInt programIdColNo = colSet->ColNo( KIptvEpgProgramIdCol );
+	TInt nameColNo = colSet->ColNo( KIptvEpgProgramNameCol );
+	CleanupStack::PopAndDestroy( colSet );
+	
+	view.FirstL();
+	TInt err( KErrNone );
+	TLinearOrder<CIptvEpgProgram> order( 
+						CIptvEpgProgram::LinearOrderOfProgramsByName );
+	CIptvEpgProgram* program = NULL;
+
+	while ( view.AtRow() )
+		{
+		view.GetL();
+		program = CIptvEpgProgram::NewL();
+		CleanupStack::PushL( program );
+		program->SetProgramId( view.ColInt64( programIdColNo ) );
+		program->SetProgramName( view.ColDes( nameColNo ).AllocL() );
+		
+		err = aResultArray->InsertInOrder( program, order );
+		if ( err != KErrNone )
+			{
+			LIVE_TV_TRACE2(_L("CIptvEpgDatabase::FetchProgramNamesFromTableL() InsertInOrder FAILED: %d"), err);
+			// KErrAlreadyExists == duplicate entry
+			if ( err != KErrAlreadyExists ) 
+				{
+				CleanupStack::PopAndDestroy( program );
+				User::Leave( err );
+				}
+			else
+				{
+				TInt index( aResultArray->FindInOrder( program, order ) );
+				if ( index != KErrNotFound )
+					{
+					User::LeaveIfError( aResultArray->Insert( program, index ) );
+					}
+				else
+					{
+					LIVE_TV_TRACE1(_L("aResultArray->FindInOrder( program, order ) == KErrNotFound!)"));
+					}
+				}
+			
+			}
+		CleanupStack::Pop( program );
+		view.NextL();
+		}
+	CleanupStack::PopAndDestroy( &view ); // closes view
+	LIVE_TV_TRACE2(_L("CIptvEpgDatabase::FetchProgramNamesFromTableL out, return %d items"), aResultArray->Count() );
+	}
+
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::FetchSchedulesFromTableL()
+//
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::FetchSchedulesFromTableL( const TDesC& aSqlStatement,
+							RPointerArray<CIptvEpgSchedule>* aResultArray )
+	{
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::FetchSchedulesFromTableL in"));
+
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	if ( !aResultArray )
+		{
+		User::Leave( KErrArgument );
+		}
+	RDbView view;
+	CleanupClosePushL( view );
+
+	User::LeaveIfError( view.Prepare( iMulticastDb, 
+									  TDbQuery( aSqlStatement ) ) );
+									  
+	User::LeaveIfError( view.EvaluateAll() );
+	
+	CDbColSet* colSet = view.ColSetL();
+	CleanupStack::PushL( colSet );
+	TInt programIdColNo = colSet->ColNo( KIptvEpgScheduleProgramIdCol );
+	TInt channelIdColNo = colSet->ColNo( KIptvEpgScheduleChannelIdCol );
+	TInt serviceIdColNo = colSet->ColNo( KIptvEpgScheduleServiceProviderIdCol );
+	TInt startTimeColNo = colSet->ColNo( KIptvEpgScheduleStartTimeCol );
+	TInt endTimeColNo = colSet->ColNo( KIptvEpgScheduleEndTimeCol );
+	CleanupStack::PopAndDestroy( colSet );
+	
+	view.FirstL();
+	while ( view.AtRow() )
+		{
+		view.GetL();
+		CIptvEpgSchedule* schedule= CIptvEpgSchedule::NewL();
+		CleanupStack::PushL( schedule );
+		schedule->iProgramId = view.ColInt64( programIdColNo );
+		schedule->iChannelId = view.ColInt64( channelIdColNo );
+		schedule->iServiceId = view.ColUint32( serviceIdColNo );
+		schedule->iStartTime = view.ColTime( startTimeColNo );
+		schedule->iEndTime = view.ColTime( endTimeColNo );
+
+		// Since now ownership of CIptvEpgProgram object is in RPointerArray	
+		aResultArray->AppendL( schedule );
+		
+		CleanupStack::Pop( schedule );
+		
+		view.NextL();
+		}
+		
+	CleanupStack::PopAndDestroy( &view ); // closes view
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::FetchSchedulesFromTableL out"));
+	}
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::FetchSearchSchedulesFromTableL()
+//
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::FetchSearchSchedulesFromTableL( const TDesC& aSqlStatement,
+						RPointerArray<CIptvEpgScheduleSearch>* aResultArray )
+	{
+
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::FetchSearchSchedulesFromTableL in"));
+	if ( !aResultArray )
+		{
+		User::Leave( KErrArgument );
+		}
+	RDbView view;
+	CleanupClosePushL( view );
+
+	User::LeaveIfError( view.Prepare( iMulticastDb, 
+									  TDbQuery( aSqlStatement ) ) );
+									  
+	User::LeaveIfError( view.EvaluateAll() );
+	
+	CDbColSet* colSet = view.ColSetL();
+	CleanupStack::PushL( colSet );
+	TInt programIdColNo = colSet->ColNo( KIptvEpgScheduleProgramIdCol );
+	TInt channelIdColNo = colSet->ColNo( KIptvEpgScheduleChannelIdCol );
+	//TInt serviceIdColNo = colSet->ColNo( KIptvEpgScheduleServiceProviderIdCol );
+	TInt startTimeColNo = colSet->ColNo( KIptvEpgScheduleStartTimeCol );
+	TInt endTimeColNo = colSet->ColNo( KIptvEpgScheduleEndTimeCol );
+
+	CleanupStack::PopAndDestroy( colSet );
+
+	CIptvEpgScheduleSearch* scheduleSearch = NULL;
+
+	view.FirstL();
+	while ( view.AtRow() )
+		{
+		view.GetL();
+		scheduleSearch = CIptvEpgScheduleSearch::NewL();
+		CleanupStack::PushL( scheduleSearch );
+		scheduleSearch->iProgramId = view.ColInt64( programIdColNo );
+		scheduleSearch->iChannelId = view.ColInt64( channelIdColNo );
+		//scheduleSearch->iServiceId = view.ColUint32( serviceIdColNo );
+		scheduleSearch->iStartTime = view.ColTime( startTimeColNo );
+		scheduleSearch->iEndTime = view.ColTime( endTimeColNo );
+		aResultArray->AppendL( scheduleSearch );
+		// Since now ownership of object is in RPointerArray	
+		CleanupStack::Pop( scheduleSearch );
+		
+		view.NextL();
+		}
+	CleanupStack::PopAndDestroy( &view ); // closes view
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::FetchSearchSchedulesFromTableL out"));
+	}
+
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::InsertOrUpdateScheduleL()
+//
+// ---------------------------------------------------------------------------
+EXPORT_C void CIptvEpgDatabase::InsertOrUpdateScheduleL( const CIptvEpgSchedule& aSchedule )
+	{
+
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	// Just add schedule because we are updating the epg to an empty database
+	AddScheduleL( aSchedule );
+	}
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::AddScheduleL()
+//
+// ---------------------------------------------------------------------------
+EXPORT_C void CIptvEpgDatabase::AddScheduleL( const CIptvEpgSchedule& aSchedule )
+	{
+
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	TBuf<50> sqlStatement;
+	sqlStatement.Append( _L("SELECT * FROM ") );
+	sqlStatement.Append( KIptvEpgScheduleTable );
+    RDbView view;
+    CleanupClosePushL( view );
+    User::LeaveIfError( view.Prepare( iMulticastDb,
+    					TDbQuery( sqlStatement ),
+    					TDbWindow::EUnlimited,
+    					RDbView::EInsertOnly ) );
+    view.InsertL();
+    
+    CDbColSet* scheduleColSet = view.ColSetL();
+    // Ownership of CDbColSet object is now here!
+    CleanupStack::PushL( scheduleColSet );
+    view.SetColL( scheduleColSet->ColNo( KIptvEpgScheduleServiceProviderIdCol ), 
+										 aSchedule.iServiceId );
+    view.SetColL( scheduleColSet->ColNo( KIptvEpgScheduleChannelIdCol ),
+										 aSchedule.iChannelId );
+    view.SetColL( scheduleColSet->ColNo( KIptvEpgScheduleProgramIdCol ), 
+										 aSchedule.iProgramId );
+    view.SetColL( scheduleColSet->ColNo( KIptvEpgScheduleStartTimeCol ), 
+										 aSchedule.iStartTime );
+    view.SetColL( scheduleColSet->ColNo( KIptvEpgScheduleEndTimeCol ), 
+										 aSchedule.iEndTime );
+										 
+	CleanupStack::PopAndDestroy( scheduleColSet );
+	view.PutL();
+
+	CleanupStack::PopAndDestroy( &view ); // closes view
+	}
+	
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::InsertOrUpdateChannelL()
+// 
+// ---------------------------------------------------------------------------
+EXPORT_C void CIptvEpgDatabase::InsertOrUpdateChannelL(
+								const CIptvEpgChannel& aChannel,
+								TUint32& aChannelKey )
+	{
+
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	// Just call AddChannelL because we are using an empty database
+	AddChannelL( aChannel, aChannelKey );
+	}
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::AddSchedulesL()
+// 
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CIptvEpgDatabase::AddSchedulesL( const RPointerArray<CIptvEpgSchedule>& aSchedules )
+	{
+
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	TBuf<50> sqlStatement;
+	sqlStatement.Append( _L("SELECT * FROM ") );
+	sqlStatement.Append( KIptvEpgScheduleTable );
+    RDbView view;
+    CleanupClosePushL( view );
+    User::LeaveIfError( view.Prepare( iMulticastDb,
+    					TDbQuery( sqlStatement ),
+    					TDbWindow::EUnlimited,
+    					RDbView::EInsertOnly ) );
+    
+    CIptvEpgSchedule* schedule = NULL;
+    LIVE_TV_TRACE2( _L("About to enter loop to insert %d schedules"), aSchedules.Count() );
+    for( TInt i = 0; i < aSchedules.Count(); i++ )
+    	{
+    	schedule = aSchedules[i];
+	    view.InsertL();
+	    
+	    CDbColSet* scheduleColSet = view.ColSetL();
+	    // Ownership of CDbColSet object is now here!
+	    CleanupStack::PushL( scheduleColSet );
+	    view.SetColL( scheduleColSet->ColNo( KIptvEpgScheduleServiceProviderIdCol ), 
+											 schedule->iServiceId );
+	    view.SetColL( scheduleColSet->ColNo( KIptvEpgScheduleChannelIdCol ),
+											 schedule->iChannelId );
+	    view.SetColL( scheduleColSet->ColNo( KIptvEpgScheduleProgramIdCol ), 
+											 schedule->iProgramId );
+	    view.SetColL( scheduleColSet->ColNo( KIptvEpgScheduleStartTimeCol ), 
+											 schedule->iStartTime );
+	    view.SetColL( scheduleColSet->ColNo( KIptvEpgScheduleEndTimeCol ), 
+											 schedule->iEndTime );
+											 
+		CleanupStack::PopAndDestroy( scheduleColSet );
+		view.PutL();
+		}
+
+	// Compact database
+	iMulticastDb.Compact();
+
+	CleanupStack::PopAndDestroy( &view ); // closes view
+	}
+	
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::AddChannelL()
+//
+// ---------------------------------------------------------------------------
+EXPORT_C void CIptvEpgDatabase::AddChannelL( const CIptvEpgChannel& aChannel,
+											 TUint32& aChannelKey )
+    {	 
+    LIVE_TV_TRACE1(_L("CIptvEpgDatabase::AddChannelL()") );
+    LIVE_TV_TRACE2( _L("aChannel.iChannelId = %Li"), aChannel.ChannelId() );
+
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+    RDbView view;
+    CleanupClosePushL( view );
+    User::LeaveIfError( view.Prepare( iMulticastDb,
+    					TDbQuery( iSqlChannel ),
+    					TDbWindow::EUnlimited,
+    					RDbView::EInsertOnly ) );
+    view.InsertL();
+    
+    CDbColSet* channelColSet = view.ColSetL();
+    // Ownership of CDbColSet object is now here!
+    CleanupStack::PushL( channelColSet );
+    view.SetColL( channelColSet->ColNo( KIptvEpgChannelIdCol ), 
+										aChannel.ChannelId() );
+    view.SetColL( channelColSet->ColNo( KIptvEpgChannelServProviderIdCol ),
+										aChannel.ServiceId() );
+    if ( aChannel.ChannelName().Length() > KIptvEpgChannelNameMaxLength )
+        {
+        // Channel name is too long, cut it
+        TBuf <KIptvEpgChannelNameMaxLength> channelName = 
+            aChannel.ChannelName().Left( KIptvEpgChannelNameMaxLength );
+        view.SetColL( channelColSet->ColNo( KIptvEpgChannelNameCol ), 
+										    channelName );
+        }
+     else
+        {
+        view.SetColL( channelColSet->ColNo( KIptvEpgChannelNameCol ), 
+										aChannel.ChannelName() );    
+        }
+    
+    view.SetColL( channelColSet->ColNo( KIptvEpgChannelLogoPathCol ), 
+										aChannel.ChannelLogoPath() );
+    
+    if ( aChannel.ChannelDescription().Length() > KIptvEpgDescrMaxLength )
+        {
+        // Channel description is too long, cut it
+        TBuf<KIptvEpgDescrMaxLength> channelDesc = 
+            aChannel.ChannelDescription().Left( KIptvEpgDescrMaxLength );
+        view.SetColL( channelColSet->ColNo( KIptvEpgChannelDescriptionCol ), 
+										channelDesc );
+        }
+    else
+        {
+        view.SetColL( channelColSet->ColNo( KIptvEpgChannelDescriptionCol ), 
+										aChannel.ChannelDescription() );    
+        }
+    
+    view.SetColL( channelColSet->ColNo( KIptvEpgChannelURICol ), 
+										aChannel.ChannelURI() );
+    
+	// SDP is long one, it needs to be handled by stream
+	RDbColWriteStream write;
+	write.OpenLC( view, channelColSet->ColNo( KIptvEpgChannelSDPCol ) );
+	write.WriteL( aChannel.ChannelSDP() );
+	write.Close();
+	CleanupStack::PopAndDestroy(); // write
+
+    TInt keyColumnNo = channelColSet->ColNo( KIptvEpgChannelDbKeyCol );                                     
+ 	
+	// Order
+	view.SetColL( channelColSet->ColNo( KIptvEpgChannelOrderCol ),
+				  aChannel.ChannelOrder() );
+	CleanupStack::PopAndDestroy( channelColSet );
+    view.PutL();
+
+    // Get new channel key
+    aChannelKey = view.ColUint32( keyColumnNo );
+    
+	CleanupStack::PopAndDestroy( &view ); // closes view
+
+	// Finally update order numbers because new channel was addded
+	UpdateChannelOrdersL( aChannel.ServiceId() );
+	}
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::InsertOrUpdateProgramL()
+//
+// ---------------------------------------------------------------------------
+EXPORT_C void CIptvEpgDatabase::InsertOrUpdateProgramL(
+										const CIptvEpgProgram& aProgram,
+        							 	TUint32& aProgramKey )
+	{
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	// Just add program because we are using an empty db
+	AddProgramL( aProgram, aProgramKey );
+	}
+
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::AddProgramL()
+//
+// ---------------------------------------------------------------------------
+EXPORT_C void CIptvEpgDatabase::AddProgramL( const CIptvEpgProgram& aProgram,
+									TUint32& aProgramKey )
+    {
+    LIVE_TV_TRACE1(_L("CIptvEpgDatabase::AddProgramL() in"));
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+    RDbView view;
+    TInt err = KErrNone;
+    CleanupClosePushL( view );
+    err = view.Prepare( iMulticastDb,
+    					TDbQuery( iSqlProgram ),
+    					TDbWindow::EUnlimited,
+    					RDbView::EInsertOnly );
+    if ( err != KErrNone )
+    	{
+    	LIVE_TV_TRACE1( _L(""));
+    	LIVE_TV_TRACE2( _L("CIptvEpgDatabase::AddProgramL FAILED with code %d"), err );
+    	LIVE_TV_TRACE1( _L(""));
+    	User::Leave( err );
+    	}
+    view.InsertL();
+    
+    CDbColSet* programColSet = view.ColSetL();
+    CleanupStack::PushL( programColSet );
+
+	view.SetColL( programColSet->ColNo( KIptvEpgProgramIdCol ), 
+										aProgram.ProgramId() );
+	view.SetColL( programColSet->ColNo( KIptvEpgProgramChannelId ),
+										aProgram.ChannelId() );
+	view.SetColL( programColSet->ColNo( KIptvEpgProgramServProviderIdCol ),
+										aProgram.ServiceId() );
+	view.SetColL( programColSet->ColNo( KIptvEpgProgramURICol ), 
+										aProgram.ProgramURI() );
+	view.SetColL( programColSet->ColNo( KIptvEpgProgramGenreCol ), 
+										aProgram.ProgramGenre() );
+    if ( aProgram.ProgramName().Length() > KIptvEpgProgramMaxLength )
+        {
+        TBuf<KIptvEpgProgramMaxLength> programName = 
+            aProgram.ProgramName().Left( KIptvEpgProgramMaxLength );
+        view.SetColL( programColSet->ColNo( KIptvEpgProgramNameCol ), 
+										programName );
+        }
+    else
+        {
+        view.SetColL( programColSet->ColNo( KIptvEpgProgramNameCol ), 
+										aProgram.ProgramName() );    
+        }
+	
+	view.SetColL( programColSet->ColNo( KIptvEpgProgramLanguageCol ), 
+										aProgram.ProgramLanguage() );
+	view.SetColL( programColSet->ColNo( KIptvEpgProgramParentalRatingCol ), 
+										aProgram.ProgramParentalRating() );
+
+	// Description is long one, it needs to be handled by stream
+	RDbColWriteStream write;
+	write.OpenLC( view, programColSet->ColNo( KIptvEpgProgramDescriptionCol ) );
+	write.WriteL( aProgram.ProgramDescription() );
+	write.Close();
+	CleanupStack::PopAndDestroy(); // write
+
+	TInt keyColumnNo = programColSet->ColNo( KIptvEpgProgramDbKeyCol );
+    CleanupStack::PopAndDestroy( programColSet );
+    view.PutL();
+
+    // Get new program key
+    aProgramKey = view.ColUint32( keyColumnNo );
+    CleanupStack::PopAndDestroy( &view ); // closes view
+    
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::AddProgramL() out"));
+    }
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::AddProgramsL()
+//
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CIptvEpgDatabase::AddProgramsL(
+						const RPointerArray<CIptvEpgProgram>& aPrograms )
+	{
+    LIVE_TV_TRACE1(_L("CIptvEpgDatabase::AddProgramsL() in"));
+	
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+    RDbView view;
+    TInt err = KErrNone;
+    CleanupClosePushL( view );
+    err = view.Prepare( iMulticastDb,
+    					TDbQuery( iSqlProgram ),
+    					TDbWindow::EUnlimited,
+    					RDbView::EInsertOnly );
+    if ( err != KErrNone )
+    	{
+    	LIVE_TV_TRACE1( _L(""));
+    	LIVE_TV_TRACE2( _L("CIptvEpgDatabase::AddProgramsL FAILED with code %d"), err );
+    	LIVE_TV_TRACE1( _L(""));
+    	User::Leave( err );
+    	}
+    
+    CIptvEpgProgram* program = NULL;
+    LIVE_TV_TRACE2( _L("About to enter loop to insert %d programs to the database"), aPrograms.Count() );
+    for( TInt i = 0; i < aPrograms.Count(); i++ )
+    	{
+	    view.InsertL();
+    	program = aPrograms[i];
+    	
+	    CDbColSet* programColSet = view.ColSetL();
+	    CleanupStack::PushL( programColSet );
+
+		view.SetColL( programColSet->ColNo( KIptvEpgProgramIdCol ), 
+											program->ProgramId() );
+		view.SetColL( programColSet->ColNo( KIptvEpgProgramChannelId ),
+											program->ChannelId() );
+		view.SetColL( programColSet->ColNo( KIptvEpgProgramServProviderIdCol ),
+											program->ServiceId() );
+		view.SetColL( programColSet->ColNo( KIptvEpgProgramURICol ), 
+											program->ProgramURI() );
+		view.SetColL( programColSet->ColNo( KIptvEpgProgramGenreCol ), 
+											program->ProgramGenre() );
+
+        if ( program->ProgramName().Length() > KIptvEpgProgramMaxLength )
+            {
+            TBuf<KIptvEpgProgramMaxLength> programName = 
+                program->ProgramName().Left( KIptvEpgProgramMaxLength );
+            view.SetColL( programColSet->ColNo( KIptvEpgProgramNameCol ), 
+                programName );
+            }
+        else
+            {
+            view.SetColL( programColSet->ColNo( KIptvEpgProgramNameCol ), 
+                program->ProgramName() );
+            }
+		view.SetColL( programColSet->ColNo( KIptvEpgProgramLanguageCol ), 
+											program->ProgramLanguage() );
+		view.SetColL( programColSet->ColNo( KIptvEpgProgramParentalRatingCol ), 
+											program->ProgramParentalRating() );
+
+		// Description is long one, it needs to be handled by stream
+		RDbColWriteStream write;
+		write.OpenLC( view, programColSet->ColNo( KIptvEpgProgramDescriptionCol ) );
+		write.WriteL( program->ProgramDescription() );
+		write.Close();
+		CleanupStack::PopAndDestroy(); // write
+	    CleanupStack::PopAndDestroy( programColSet );
+	    view.PutL();
+    	}
+    CleanupStack::PopAndDestroy( &view ); // closes view
+
+	iMulticastDb.Compact();
+    
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::AddProgramsL() out"));
+	}
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::AddProgramWithScheduleL()
+//
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CIptvEpgDatabase::AddProgramWithScheduleL(
+							CIptvEpgProgramWithSchedule& aProgramWithSchedule,
+							TUint32& aProgramKey )
+	{
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	AddProgramL( aProgramWithSchedule, aProgramKey );
+	AddScheduleL( aProgramWithSchedule.Schedule() );
+	}
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::AddProgramsWithSchedulesL()
+//
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CIptvEpgDatabase::AddProgramsWithSchedulesL(
+					const RPointerArray<CIptvEpgProgramWithSchedule>& aProgramsWithSchedules )
+	{
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	RPointerArray<CIptvEpgSchedule> scheduleArray;
+	CleanupClosePushL( scheduleArray );
+	RPointerArray<CIptvEpgProgram> programArray;
+	CleanupClosePushL( programArray );
+
+	CIptvEpgProgramWithSchedule* progWithSchedule = NULL;
+	TInt err( KErrNone );
+	for ( TInt i = 0; i < aProgramsWithSchedules.Count() && err == KErrNone; i++ )
+		{
+		progWithSchedule = aProgramsWithSchedules[i];
+		CIptvEpgSchedule& schedule = progWithSchedule->Schedule();
+		err = scheduleArray.Append( &schedule );
+		if ( err == KErrNone )
+			{
+			err = programArray.Append( progWithSchedule );
+			}
+		}
+	if ( err != KErrNone )
+		{
+		LIVE_TV_TRACE2(_L("CIptvEpgDatabase::AddProgramsWithSchedulesL: Append in for-loop FAILED: %d"), err);
+		scheduleArray.Reset();
+		programArray.Reset();
+		User::Leave( err );
+		}
+	if ( programArray.Count() > 0 )
+		{
+		AddProgramsL( programArray );
+		if ( scheduleArray.Count() > 0 )
+			{
+			AddSchedulesL( scheduleArray );
+			}
+		}
+	programArray.Reset();
+	scheduleArray.Reset();
+	CleanupStack::PopAndDestroy( &programArray );
+	CleanupStack::PopAndDestroy( &scheduleArray );
+	}
+
+// ---------------------------------------------------------
+// CIptvEpgDatabase::UpdateChannelOrderL()
+//
+// ---------------------------------------------------------
+EXPORT_C void CIptvEpgDatabase::UpdateChannelOrderL( const TUint32 aServiceId,
+													 const TInt64  aChannelId,
+													 const TUint32 aOrder )
+    {
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	LIVE_TV_TRACE4(_L("CIptvEpgDatabase::UpdateChannelOrderL in, aServiceId: %u, aChannelId: %Li, aOrder:%u"), aServiceId, aChannelId, aOrder );
+    TBuf<KCustomSqlLength> sqlStatement;
+    sqlStatement.Append( _L("SELECT ") );
+	sqlStatement.Append( KIptvEpgChannelOrderCol );
+    sqlStatement.Append( _L(" FROM ") );
+    sqlStatement.Append( KIptvEpgChannelTable );
+    sqlStatement.Append( _L(" WHERE ") );
+    sqlStatement.Append( KIptvEpgChannelIdCol );
+    sqlStatement.Append( _L(" = ") );
+    sqlStatement.AppendNum( aChannelId );
+    sqlStatement.Append( _L(" AND ") );
+	sqlStatement.Append( KIptvEpgChannelServProviderIdCol );
+	sqlStatement.Append( _L(" = ") );
+    sqlStatement.AppendNum( aServiceId );
+   
+    RDbView view;
+    CleanupClosePushL( view );
+	User::LeaveIfError( iMulticastDb.Begin() );
+    User::LeaveIfError( view.Prepare( iMulticastDb,
+    								  TDbQuery( sqlStatement ) ) );
+    User::LeaveIfError( view.EvaluateAll() );
+    
+    // Ownership of this pointer is now here. It needs to be deleted also
+    CDbColSet* channelColSet = view.ColSetL();
+    CleanupStack::PushL( channelColSet );
+    
+	// sql statement found a row from table
+    if ( view.FirstL() )
+    	{
+		view.UpdateL();
+		
+	    view.SetColL( channelColSet->ColNo( KIptvEpgChannelOrderCol ), 
+					  aOrder );
+		
+		view.PutL();
+    	}
+    CleanupStack::PopAndDestroy( channelColSet );
+    CleanupStack::PopAndDestroy( &view ); // closes view
+	User::LeaveIfError( iMulticastDb.Commit() );
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::UpdateChannelOrderL() out"));
+    }    
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::DeleteChannelL()
+//
+// ---------------------------------------------------------------------------
+EXPORT_C void CIptvEpgDatabase::DeleteChannelL( 
+										const TUint32 aServiceProviderId, 
+										const TInt64 aChannelId )
+	{
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	// First of all we need to delete all the programs which belongs to
+	// channel identified by aServiceProviderId and aChannelId
+	TBuf<KCustomSqlLength> sqlStatement;
+	sqlStatement.Append( _L("SELECT ") );
+	sqlStatement.Append( KIptvEpgProgramIdCol );
+	sqlStatement.Append( _L(" FROM ") );
+	sqlStatement.Append( KIptvEpgProgramTable );
+	sqlStatement.Append( _L(" WHERE ") );
+	sqlStatement.Append( KIptvEpgProgramChannelId );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aChannelId );
+	sqlStatement.Append( _L(" AND ") );
+	sqlStatement.Append( KIptvEpgProgramServProviderIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aServiceProviderId );
+
+	RDbView view;
+	CleanupClosePushL( view );
+	User::LeaveIfError( view.Prepare( iMulticastDb, 
+									  TDbQuery( sqlStatement ) ) );
+	User::LeaveIfError( view.EvaluateAll() );
+	view.FirstL();
+	CDbColSet* colSet = view.ColSetL();
+	CleanupStack::PushL( colSet );
+	TInt programIdColNo = colSet->ColNo( KIptvEpgProgramIdCol );
+	CleanupStack::PopAndDestroy( colSet );
+	
+	RArray<TInt64> programIdArray;
+	CleanupClosePushL( programIdArray );
+	while ( view.AtRow() )
+		{
+		view.GetL();
+		User::LeaveIfError( programIdArray.Append( 
+								view.ColInt64( programIdColNo ) ) );
+		view.NextL();
+		}
+	for ( TInt i = 0; i < programIdArray.Count(); i++ )
+		{
+		DeleteProgramL( aServiceProviderId, programIdArray[i] );
+		}
+	programIdArray.Reset();
+	CleanupStack::PopAndDestroy( &programIdArray ); // closes programIdArray
+	CleanupStack::PopAndDestroy( &view ); // closes view
+
+	// Handle channel removal
+	sqlStatement.Zero();
+	sqlStatement.Append( _L("SELECT * FROM ") );
+	sqlStatement.Append( KIptvEpgChannelTable );
+	sqlStatement.Append( _L(" WHERE ") );
+	sqlStatement.Append( KIptvEpgChannelIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aChannelId );
+	sqlStatement.Append( _L(" AND ") );
+	sqlStatement.Append( KIptvEpgChannelServProviderIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aServiceProviderId );
+
+	User::LeaveIfError( iMulticastDb.Begin() );
+	CleanupClosePushL( view );
+	User::LeaveIfError( view.Prepare( iMulticastDb, 
+									  TDbQuery( sqlStatement ) ) );
+	User::LeaveIfError( view.EvaluateAll() );
+
+	while ( view.NextL() )
+		{
+		view.DeleteL();
+		}
+	CleanupStack::PopAndDestroy( &view ); // Closes view
+	User::LeaveIfError( iMulticastDb.Commit() );
+
+	// Update the channel order numbers
+	UpdateChannelOrdersL( aServiceProviderId );
+	}
+	
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::UpdateChannelOrdersL()
+//
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::UpdateChannelOrdersL( const TUint32 aServiceProviderId ) 
+	{
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+
+	TBuf<KCustomSqlLength> sqlStatement;
+	sqlStatement.Append( _L("SELECT " ) );
+	sqlStatement.Append( KIptvEpgChannelServProviderIdCol );
+	sqlStatement.Append( _L(", "));
+	sqlStatement.Append( KIptvEpgChannelIdCol );
+	sqlStatement.Append( _L(", "));
+	sqlStatement.Append( KIptvEpgChannelURICol );
+	sqlStatement.Append( _L(", "));
+	sqlStatement.Append( KIptvEpgChannelOrderCol );
+	sqlStatement.Append( _L(" FROM ") );
+	sqlStatement.Append( KIptvEpgChannelTable );
+	sqlStatement.Append( _L(" WHERE ") );
+	sqlStatement.Append( KIptvEpgChannelServProviderIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aServiceProviderId );
+	sqlStatement.Append( _L(" ORDER BY ") );
+	sqlStatement.Append( KIptvEpgChannelOrderCol );
+	
+	RDbView view;
+	CleanupClosePushL( view );
+	User::LeaveIfError( view.Prepare( iMulticastDb, 
+						TDbQuery( sqlStatement ) ) );
+	User::LeaveIfError( view.EvaluateAll() );
+	view.FirstL();
+	CDbColSet* colSetOrder = view.ColSetL();
+	CleanupStack::PushL( colSetOrder );
+	const TInt serviceColNo = colSetOrder->ColNo( KIptvEpgChannelServProviderIdCol );
+	const TInt channelIdColNo = colSetOrder->ColNo( KIptvEpgChannelIdCol );
+	const TInt orderColNo = colSetOrder->ColNo( KIptvEpgChannelOrderCol );
+	const TInt uriColNo = colSetOrder->ColNo( KIptvEpgChannelURICol );
+	CleanupStack::PopAndDestroy( colSetOrder );
+
+	RArray<TUint32> orderArray;
+	CleanupClosePushL( orderArray );
+	RArray<TUint32> serviceArray;
+	CleanupClosePushL( serviceArray );
+	RArray<TInt64> channelIdArray;
+	CleanupClosePushL( channelIdArray );
+    CDesCArray* uriArray = new ( ELeave ) CDesCArrayFlat( KIptvDefaultUriCount  );
+	CleanupStack::PushL( uriArray );
+
+	while ( view.AtRow() ) 
+		{
+		view.GetL();
+		User::LeaveIfError( orderArray.Append( 
+								view.ColUint32( orderColNo ) ) );
+		User::LeaveIfError( serviceArray.Append( 
+							view.ColUint32( serviceColNo ) ) );
+		User::LeaveIfError( channelIdArray.Append( 
+							view.ColInt64( channelIdColNo ) ) );
+	    uriArray->AppendL( view.ColDes( uriColNo ) );
+		view.NextL();
+		}
+	
+	RArray<TUint32> zeroServiceIdArray;
+	CleanupClosePushL( zeroServiceIdArray );
+	RArray<TInt64> zeroChanIdArray;
+	CleanupClosePushL( zeroChanIdArray );
+	CDesCArray* zeroUriArray = new ( ELeave ) CDesCArrayFlat( KIptvDefaultUriCount  );
+	CleanupStack::PushL( zeroUriArray );
+    
+	// Get all channels whose order is zero
+	for ( TInt i = orderArray.Count() - 1; i >= 0; i-- ) 
+		{
+		if ( orderArray[i] == 0 ) 
+			{
+			if ( i < serviceArray.Count() && i < channelIdArray.Count() &&
+			     i < uriArray->MdcaCount() )
+			    {
+			    zeroServiceIdArray.AppendL( serviceArray[i] );
+			    zeroChanIdArray.AppendL( channelIdArray[i] );
+			    zeroUriArray->AppendL( uriArray->MdcaPoint( i )  );    
+			    }
+			orderArray.Remove( i );
+			serviceArray.Remove( i );
+			channelIdArray.Remove( i );
+			uriArray->Delete( i );
+			}
+		}
+    TUint32 prev( 0 );
+    TUint32 current( 0 );		
+	// remove all deactivated channels
+	// by default all channels are active so if there are
+	// any channels that have been deactivated, it means that user
+	// has deactivated them -> we don't need to care about
+	// channels that have no stream URL
+	for ( TInt j = orderArray.Count() - 1; j >= 0; j-- ) 
+		{
+		current = orderArray[j];
+		if ( current == KMaxTUint32 ) 
+			{
+			orderArray.Remove( j );
+			serviceArray.Remove( j );
+			channelIdArray.Remove( j );
+			uriArray->Delete( j );
+			}
+		else if ( j < uriArray->Count() && uriArray->MdcaPoint( j ).Length() == 0 )
+		    {
+		    // Channel has no stream URL, put those also to zero array
+		    // they are handled later
+		    zeroServiceIdArray.AppendL( serviceArray[j] );
+		    zeroChanIdArray.AppendL( channelIdArray[j] );
+		    zeroUriArray->AppendL( uriArray->MdcaPoint( j ) );
+		    orderArray.Remove( j );
+		    serviceArray.Remove( j );
+		    channelIdArray.Remove( j );
+		    uriArray->Delete( j );
+		    }
+		}
+	// now orderArray should contain only activated channels
+	// check if channel orders are "in order" i.e. UI does not want to see 
+	// orders like 1, 2, 4, 5, 6 if one channel has been deleted.
+    for ( TInt k = 0; k < orderArray.Count(); k++ ) 
+        {
+        current = orderArray[k];
+        if ( k == 0 && current != 1 )
+            {
+            // First one is not number 1, fix
+            orderArray[k] = 1;
+            UpdateChannelOrderL( serviceArray[k], channelIdArray[k],
+                                 orderArray[k] );
+            }
+        if ( k > 0 ) 
+            {
+            prev = orderArray[k-1];
+            }
+		
+        if ( current < KMaxTUint32 && k > 0 && 
+             prev < KMaxTUint32 )
+            {
+            const TInt offset( TInt( current - prev ) );
+
+            if ( offset != 1 ) 
+                {
+                // channel orders have gone wrong, fix
+                orderArray[k] = prev + 1;
+                UpdateChannelOrderL( serviceArray[k], channelIdArray[k],
+                                     orderArray[k] );
+				}
+			}
+		}
+	
+	// now set channel order for channels whose order is 0 and
+	// stream URL is available
+	TUint32 max( 0 );
+	if ( orderArray.Count() > 0  )
+		{
+        max = orderArray[orderArray.Count()-1];    
+		}
+    TInt l( 0 );
+    for ( l = zeroServiceIdArray.Count() - 1; l >= 0; l-- )
+        {
+        if ( max < ( KMaxTUint32 - 1 ) ) 
+            {
+            if ( zeroUriArray->MdcaPoint( l ).Length() > 0 &&
+			     max < ( KMaxTUint32 - 1 ) )
+                {
+                max++;
+                UpdateChannelOrderL( zeroServiceIdArray[l], zeroChanIdArray[l], 
+							 	 max );
+                zeroServiceIdArray.Remove( l );
+                zeroChanIdArray.Remove( l );
+                zeroUriArray->Delete( l );
+                }
+		    }
+        }
+    // Let's move the channels that have no stream URL to last position
+    // in active channel list
+    for ( l = 0; l < zeroServiceIdArray.Count() && l < zeroUriArray->MdcaCount() &&
+          l < zeroChanIdArray.Count(); l++ )
+		{
+		if ( zeroUriArray->MdcaPoint( l ).Length() == 0 && max < ( KMaxTUint32 - 1 ) )
+		    {
+		    max++;
+		    UpdateChannelOrderL( zeroServiceIdArray[l], zeroChanIdArray[l],
+		                         max );
+		    }
+		}    
+    
+    zeroServiceIdArray.Reset();
+	zeroChanIdArray.Reset();
+	orderArray.Reset();
+	channelIdArray.Reset();
+	serviceArray.Reset();
+	
+	CleanupStack::PopAndDestroy( zeroUriArray );
+	CleanupStack::PopAndDestroy( &zeroChanIdArray );
+	CleanupStack::PopAndDestroy( &zeroServiceIdArray );
+	CleanupStack::PopAndDestroy( uriArray );
+	CleanupStack::PopAndDestroy( &channelIdArray ); // Closes array
+	CleanupStack::PopAndDestroy( &serviceArray ); // Closes array
+	CleanupStack::PopAndDestroy( &orderArray ); // Closes array
+	CleanupStack::PopAndDestroy( &view ); // Closes view
+	}
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::DeleteProgramL()
+//
+// ---------------------------------------------------------------------------
+EXPORT_C void CIptvEpgDatabase::DeleteProgramL( 
+										const TUint32 aServiceProviderId,
+										const TInt64 aProgramId )
+	{
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	TBuf<KCustomSqlLength> sqlStatement;
+	sqlStatement.Append( _L("SELECT * FROM ") );
+	sqlStatement.Append( KIptvEpgProgramTable );
+	sqlStatement.Append( _L(" WHERE ") );
+	sqlStatement.Append( KIptvEpgProgramIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aProgramId );
+	sqlStatement.Append( _L(" AND ") );
+	sqlStatement.Append( KIptvEpgProgramServProviderIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aServiceProviderId );
+
+	User::LeaveIfError( iMulticastDb.Begin() );
+	
+	RDbView view;
+	CleanupClosePushL( view );
+	User::LeaveIfError( view.Prepare( iMulticastDb, 
+									  TDbQuery( sqlStatement ) ) );
+	User::LeaveIfError( view.EvaluateAll() );
+
+	while ( view.NextL() )
+		{
+		view.DeleteL();
+		}
+	CleanupStack::PopAndDestroy( &view ); // closes view
+	User::LeaveIfError( iMulticastDb.Commit() );
+	}
+    
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::ClearChannelTableL()
+//
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::ClearChannelTableL( const TUint32 aServiceId )
+	{
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	TBuf<KCustomSqlLength> sqlStatement;
+	sqlStatement.Append( _L("SELECT * FROM ") );
+	sqlStatement.Append( KIptvEpgChannelTable );
+	sqlStatement.Append( _L(" WHERE ") );
+	sqlStatement.Append( KIptvEpgChannelServProviderIdCol );
+	sqlStatement.Append( _L(" = " ) );
+	sqlStatement.AppendNum( aServiceId );
+	
+	RDbView view;
+	CleanupClosePushL( view );
+	User::LeaveIfError( iMulticastDb.Begin() );
+	User::LeaveIfError( view.Prepare( iMulticastDb, 
+									  TDbQuery( sqlStatement ) ) );
+	User::LeaveIfError( view.EvaluateAll() );
+	
+	while ( view.NextL() )
+		{
+		view.DeleteL();
+		}
+	CleanupStack::PopAndDestroy( &view ); // closes view
+	User::LeaveIfError( iMulticastDb.Commit() );
+	}
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::ClearProgramTableL()
+//
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::ClearProgramTableL( const TUint32 aServiceId )
+	{
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	TBuf<KCustomSqlLength> sqlStatement;
+	sqlStatement.Append( _L("SELECT * FROM ") );
+	sqlStatement.Append( KIptvEpgProgramTable );
+	sqlStatement.Append( _L(" WHERE ") );
+	sqlStatement.Append( KIptvEpgProgramServProviderIdCol );
+	sqlStatement.Append( _L(" = " ) );
+	sqlStatement.AppendNum( aServiceId );
+
+	
+	RDbView view;
+	CleanupClosePushL( view );
+	User::LeaveIfError( iMulticastDb.Begin() );
+	User::LeaveIfError( view.Prepare( iMulticastDb, 
+									  TDbQuery( sqlStatement ) ) );
+	User::LeaveIfError( view.EvaluateAll() );
+	while ( view.NextL() )
+		{
+		view.DeleteL();
+		}
+	CleanupStack::PopAndDestroy( &view ); // closes view
+	User::LeaveIfError( iMulticastDb.Commit() );
+	}
+    
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::ClearScheduleTableL()
+//
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::ClearScheduleTableL( const TUint32 aServiceId )
+	{
+
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	TBuf<KCustomSqlLength> sqlStatement;
+	sqlStatement.Append( _L("SELECT * FROM ") );
+	sqlStatement.Append( KIptvEpgScheduleTable );
+	sqlStatement.Append( _L(" WHERE ") );
+	sqlStatement.Append( KIptvEpgScheduleServiceProviderIdCol );
+	sqlStatement.Append( _L(" = " ) );
+	sqlStatement.AppendNum( aServiceId );
+
+	
+	RDbView view;
+	CleanupClosePushL( view );
+	User::LeaveIfError( iMulticastDb.Begin() );
+	User::LeaveIfError( view.Prepare( iMulticastDb, 
+									  TDbQuery( sqlStatement ) ) );
+	User::LeaveIfError( view.EvaluateAll() );
+	while ( view.NextL() )
+		{
+		view.DeleteL();
+		}
+	CleanupStack::PopAndDestroy( &view ); // closes view
+	User::LeaveIfError( iMulticastDb.Commit() );
+	}
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::ClearLatestEpgTableL()
+//
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::ClearLatestEpgTableL( const TUint32 aServiceId )
+	{
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	
+	TBuf<KCustomSqlLength> sqlStatement;
+	sqlStatement.Append( _L("SELECT * FROM ") );
+	sqlStatement.Append( KIptvEpgLatestEpgAvailableTable );
+	sqlStatement.Append( _L(" WHERE ") );
+	sqlStatement.Append( KIptvEpgLatestEpgAvailableServiceProviderIdCol );
+	sqlStatement.Append( _L(" = " ) );
+	sqlStatement.AppendNum( aServiceId );
+
+	RDbView view;
+	CleanupClosePushL( view );
+	User::LeaveIfError( iMulticastDb.Begin() );
+	User::LeaveIfError( view.Prepare( iMulticastDb, 
+									  TDbQuery( sqlStatement ) ) );
+	User::LeaveIfError( view.EvaluateAll() );
+	while ( view.NextL() )
+		{
+		view.DeleteL();
+		}
+	CleanupStack::PopAndDestroy( &view ); // closes view
+	User::LeaveIfError( iMulticastDb.Commit() );
+	}
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::ClearLastModifiedTableL()
+//
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::ClearLastModifiedTableL( const TUint32 aServiceId )
+	{
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+	TBuf<KCustomSqlLength> sqlStatement;
+	sqlStatement.Append( _L("SELECT * FROM ") );
+	sqlStatement.Append( KIptvEpgLastModifiedTable );
+	sqlStatement.Append( _L(" WHERE ") );
+	sqlStatement.Append( KIptvEpgLastModifiedTableServiceIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aServiceId );
+	
+	RDbView view;
+	CleanupClosePushL( view );
+	User::LeaveIfError( iMulticastDb.Begin() );
+	User::LeaveIfError( view.Prepare( iMulticastDb,
+									  TDbQuery( sqlStatement ) ) );
+	User::LeaveIfError( view.EvaluateAll() );
+	while ( view.NextL() )
+		{
+		view.DeleteL();
+		}
+	CleanupStack::PopAndDestroy( &view );
+	User::LeaveIfError( iMulticastDb.Commit() );
+	}
+
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::MakeSqlStrings()
+//
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::MakeSqlStrings()
+    {   
+    LIVE_TV_TRACE1(_L("CIptvEpgDatabase::MakeSqlStrings()"));
+    // Channel
+    iSqlChannel.Zero(); 
+    iSqlChannel.Append( _L("SELECT * FROM " ) );
+    iSqlChannel.Append( KIptvEpgChannelTable );   
+    
+    // Program
+    iSqlProgram.Zero(); 
+    iSqlProgram.Append( _L("SELECT * FROM ") );
+    iSqlProgram.Append( KIptvEpgProgramTable );
+    }
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::GetChannelL()
+//
+// ---------------------------------------------------------------------------
+EXPORT_C CIptvEpgChannel* CIptvEpgDatabase::GetChannelL( TInt aService,
+        								                 TInt64 aChannel )
+	{
+	if ( iLocalState == EBackup )
+		{
+		return NULL;
+		}
+
+	CIptvEpgChannel* retval = NULL;
+	TBuf<KCustomSqlLength> sqlStatement;
+    sqlStatement.Append( _L("SELECT * FROM "));
+    sqlStatement.Append( KIptvEpgChannelTable );
+    sqlStatement.Append( _L(" WHERE ") );
+    sqlStatement.Append( KIptvEpgChannelServProviderIdCol );
+    sqlStatement.Append( _L(" = ") );
+    sqlStatement.AppendNum( aService );
+	sqlStatement.Append( _L(" AND ") );
+	sqlStatement.Append( KIptvEpgChannelIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aChannel );
+
+	RPointerArray<CIptvEpgChannel> resultArray;
+	CleanupClosePushL( resultArray );
+	TRAPD( err, DoGetChannelsL( sqlStatement, &resultArray ) );
+	if ( err != KErrNone )
+		{
+		LIVE_TV_TRACE2(_L("DoGetChannelsL FAILED: %d"), err);
+		resultArray.ResetAndDestroy();
+		User::Leave( err );
+		}
+	const TInt c = resultArray.Count();
+	if ( c > 0 )
+		{
+		retval = resultArray[0];        // note, index 0 is the retval, not deleted
+		for ( TInt i( 1 ); i < c; i++ ) // note, starts from 1, not 0. 
+			{
+			delete resultArray[i]; 
+			resultArray[i] = NULL;
+			}
+		}
+	CleanupStack::PopAndDestroy( &resultArray ); // closes array
+    return retval; 
+	}
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::UpdateChannelIconPathL()
+//
+// ---------------------------------------------------------------------------
+EXPORT_C void CIptvEpgDatabase::UpdateChannelIconPathL( const TUint32 aServiceId,
+									  const TInt64  aChannelId,
+									  const TDesC&  aIconPath ) 
+	{
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::UpdateChannelIconPathL() in") );
+
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+
+	TBuf<KCustomSqlLength> sqlStatement;
+    sqlStatement.Append( _L("SELECT ") );
+	sqlStatement.Append( KIptvEpgChannelLogoPathCol );
+	sqlStatement.Append( _L(" FROM ") );
+    sqlStatement.Append( KIptvEpgChannelTable );
+    sqlStatement.Append( _L(" WHERE ") );
+    sqlStatement.Append( KIptvEpgChannelIdCol );
+    sqlStatement.Append( _L(" = ") );
+    sqlStatement.AppendNum( aChannelId );
+	sqlStatement.Append( _L(" AND ") );
+	sqlStatement.Append( KIptvEpgChannelServProviderIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aServiceId );
+   
+    RDbView view;
+    CleanupClosePushL( view );
+	User::LeaveIfError( iMulticastDb.Begin() );
+    User::LeaveIfError( view.Prepare( iMulticastDb,
+    								  TDbQuery( sqlStatement ) ) );
+    User::LeaveIfError( view.EvaluateAll() );
+    
+    // Ownership of this pointer is now here. It needs to be deleted also
+    CDbColSet* channelColSet = view.ColSetL();
+    CleanupStack::PushL( channelColSet );
+    
+    // sql statement found a row from table
+    if ( view.FirstL() )
+    	{
+    	view.UpdateL();
+	    view.SetColL( channelColSet->ColNo( KIptvEpgChannelLogoPathCol ),
+	    			  aIconPath );
+	    view.PutL();
+    	}
+    CleanupStack::PopAndDestroy( channelColSet );
+    CleanupStack::PopAndDestroy( &view ); // closes view
+	User::LeaveIfError( iMulticastDb.Commit() );
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::UpdateChannelIconPathL() out") );
+	}
+
+// METHODS FOR LATEST EPG AVAILABLE TABLE
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::CreateLatestEpgAvailableTableL()
+//
+// Creates database table for holding the start time of the latest epg data
+// available for each service provider
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::CreateLatestEpgAvailableTableL( 
+									RDbNamedDatabase& aDatabase ) const
+	{
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::CreateLatestEpgAvailableTableL"));
+	TDbCol keyCol( KIptvEpgLatestEpgAvailableTableKeyCol, EDbColUint32 );
+	keyCol.iAttributes = TDbCol::EAutoIncrement;
+	
+	TDbCol serviceIdCol( KIptvEpgLatestEpgAvailableServiceProviderIdCol, EDbColUint32 );
+	
+	TDbCol startTimeCol( KIptvEpgLatestEpgAvailableStartTimeCol, EDbColDateTime );
+	
+    CDbColSet* latestEpgAvailableColSet = CDbColSet::NewLC();
+    latestEpgAvailableColSet->AddL( keyCol );
+    latestEpgAvailableColSet->AddL( serviceIdCol );
+	latestEpgAvailableColSet->AddL( startTimeCol );
+
+        
+    User::LeaveIfError( aDatabase.CreateTable( KIptvEpgLatestEpgAvailableTable, 
+    												*latestEpgAvailableColSet ) );
+    CleanupStack::PopAndDestroy( latestEpgAvailableColSet );
+	}
+	
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::AddLatestEpgAvailableL
+//
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::AddLatestEpgAvailableL
+							( CIptvEpgLatestEpgAvailable& aLatestEpgAvailable )
+	{
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+
+	TBuf<50> sqlStatement;
+	sqlStatement.Append( _L("SELECT * FROM ") );
+	sqlStatement.Append( KIptvEpgLatestEpgAvailableTable );
+    RDbView view;
+    CleanupClosePushL( view );
+    User::LeaveIfError( view.Prepare( iMulticastDb,
+    					TDbQuery( sqlStatement ),
+    					TDbWindow::EUnlimited,
+    					RDbView::EInsertOnly ) );
+    view.InsertL();
+    
+    CDbColSet* latestEpgAvailableColSet = view.ColSetL();
+    // Ownership of CDbColSet object is now here!
+    CleanupStack::PushL( latestEpgAvailableColSet );
+    view.SetColL( latestEpgAvailableColSet->ColNo( KIptvEpgLatestEpgAvailableServiceProviderIdCol ), 
+										 aLatestEpgAvailable.iServiceId );
+
+    view.SetColL( latestEpgAvailableColSet->ColNo( KIptvEpgLatestEpgAvailableStartTimeCol ), 
+										 aLatestEpgAvailable.iStartTime );
+										 
+	CleanupStack::PopAndDestroy( latestEpgAvailableColSet );
+	view.PutL();
+
+	CleanupStack::PopAndDestroy( &view ); // closes view
+	}
+	
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::InsertOrUpdateLatestEpgAvailableL()
+//
+// ---------------------------------------------------------------------------
+EXPORT_C void CIptvEpgDatabase::InsertOrUpdateLatestEpgAvailableL
+									( CIptvEpgLatestEpgAvailable& aLatestEpgAvailable )
+	{
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+
+    TBuf<KCustomSqlLength> sqlStatement;
+    sqlStatement.Append( _L("SELECT * FROM ") );
+    sqlStatement.Append( KIptvEpgLatestEpgAvailableTable );
+    sqlStatement.Append( _L(" WHERE ") );
+	sqlStatement.Append( KIptvEpgLatestEpgAvailableServiceProviderIdCol );
+    sqlStatement.Append( _L(" = "));
+	sqlStatement.AppendNum( aLatestEpgAvailable.GetServiceId() );
+
+    RDbView view;
+    CleanupClosePushL( view );
+    User::LeaveIfError( view.Prepare( iMulticastDb,
+    								  TDbQuery( sqlStatement ) ) );
+    User::LeaveIfError( view.EvaluateAll() );
+    
+    // Ownership of this pointer is now here. It needs to be deleted also
+    CDbColSet* latestEpgAvailableColSet = view.ColSetL();
+    CleanupStack::PushL( latestEpgAvailableColSet );
+    
+    // sql statement found a row from table
+    if ( view.FirstL() ) // Update
+    	{
+    	view.UpdateL();
+    	
+		view.SetColL( latestEpgAvailableColSet->ColNo
+							( KIptvEpgLatestEpgAvailableServiceProviderIdCol ),
+					  		 aLatestEpgAvailable.GetServiceId() );
+					  
+		view.SetColL( latestEpgAvailableColSet->ColNo( KIptvEpgLatestEpgAvailableStartTimeCol ),
+					  aLatestEpgAvailable.GetStartTime() );
+
+		view.PutL();
+    	}	
+	
+	else
+		{
+		AddLatestEpgAvailableL( aLatestEpgAvailable );	
+		}
+	
+	CleanupStack::PopAndDestroy( latestEpgAvailableColSet );
+    CleanupStack::PopAndDestroy( &view ); // closes view
+	}
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::GetLatestScheduleTimeL
+//
+// ---------------------------------------------------------------------------
+EXPORT_C TTime CIptvEpgDatabase::GetLatestScheduleTimeL( const TUint32 aServiceId )
+	{
+	LIVE_TV_TRACE1( _L("CIptvEpgDatabase::GetLatestScheduleTimeL IN") );
+	if ( iLocalState == EBackup )
+		{
+		return TTime( 0 );
+		}
+	
+    TBuf<KCustomSqlLength> sqlStatement;
+    sqlStatement.Append( _L("SELECT * FROM ") );
+    sqlStatement.Append( KIptvEpgLatestEpgAvailableTable );
+    sqlStatement.Append( _L(" WHERE ") );
+	sqlStatement.Append( KIptvEpgLatestEpgAvailableServiceProviderIdCol );
+    sqlStatement.Append( _L(" = "));
+	sqlStatement.AppendNum( aServiceId );
+
+    RDbView view;
+    CleanupClosePushL( view );
+    User::LeaveIfError( view.Prepare( iMulticastDb,
+    								  TDbQuery( sqlStatement ) ) );
+    User::LeaveIfError( view.EvaluateAll() );
+    
+    // Ownership of this pointer is now here. It needs to be deleted also
+    CDbColSet* latestEpgAvailableColSet = view.ColSetL();
+    CleanupStack::PushL( latestEpgAvailableColSet );
+    TInt startTimeColNo = latestEpgAvailableColSet->ColNo( KIptvEpgLatestEpgAvailableStartTimeCol );
+    
+    TTime latestTime;
+    // sql statement found a row from table,fetch that
+    if ( view.FirstL() )  
+    	{
+		view.GetL();
+		
+		latestTime = view.ColTime( startTimeColNo );				
+		}
+	else
+		{ 
+		User::Leave( KErrNotFound );
+		}	
+	
+	CleanupStack::PopAndDestroy( latestEpgAvailableColSet );
+    CleanupStack::PopAndDestroy( &view ); // closes view
+    return latestTime;
+	}	    		
+	
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::RemoveScheduledDataFromChannelL
+//
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::RemoveScheduledDataFromChannelL( const CIptvEpgChannel& aChannel )
+	{
+	LIVE_TV_TRACE1( _L("CIptvEpgDatabase::RemoveScheduledDataFromChannelL IN") );
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+
+    TBuf<KCustomSqlLength> sqlStatement;
+    _LIT(KDeleteStatementTemplate, "SELECT %S FROM %S WHERE %S = %u AND %S = %Li"); 
+    sqlStatement.Format( KDeleteStatementTemplate,
+    					 &KIptvEpgScheduleServiceProviderIdCol,
+                         &KIptvEpgScheduleTable,
+                         &KIptvEpgScheduleServiceProviderIdCol,
+                         aChannel.ServiceId(),
+                         &KIptvEpgScheduleChannelIdCol,
+                         aChannel.ChannelId() );
+	RDbView view;
+	CleanupClosePushL( view );
+	User::LeaveIfError( view.Prepare( iMulticastDb,
+									  TDbQuery( sqlStatement ) ) );
+	User::LeaveIfError( view.EvaluateAll() );
+	User::LeaveIfError( iMulticastDb.Begin() );
+	view.FirstL();
+#if defined(LIVE_TV_FILE_TRACE) || defined(LIVE_TV_RDEBUG_TRACE)
+	TInt deleteCount = 0; 
+#endif
+	while ( view.AtRow() )
+		{
+		view.DeleteL();
+		view.NextL();
+#if defined(LIVE_TV_FILE_TRACE) || defined(LIVE_TV_RDEBUG_TRACE)		
+		deleteCount++; 
+#endif
+		}
+#if defined(LIVE_TV_FILE_TRACE) || defined(LIVE_TV_RDEBUG_TRACE)				
+	LIVE_TV_TRACE2(_L("RemoveScheduledDataFromChannelL removed %d schedules"), deleteCount );		
+#endif
+	CleanupStack::PopAndDestroy( &view ); // closes the view
+	// iMulticastDb.Compact(); 
+	User::LeaveIfError( iMulticastDb.Commit() );	
+	}
+	
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::GetSchedulesByProgIdL()
+// 
+// ---------------------------------------------------------------------------
+//
+EXPORT_C void CIptvEpgDatabase::GetSchedulesByProgIdL( 
+								const TUint32 aServiceProviderId,
+								const TInt64 aChannelKey,
+								const TInt64 aProgId,
+								RPointerArray<CIptvEpgSchedule>* aResultArray )
+    {
+    LIVE_TV_TRACE3(_L("CIptvEpgDatabase::GetSchedulesByProgIdL() ser %d program id %Li"), (int)aServiceProviderId, aProgId );
+
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+    
+	if ( !aResultArray )
+		{
+		User::Leave( KErrArgument );
+		}
+	RPointerArray<CIptvEpgProgram> programs;
+	CleanupClosePushL( programs );
+    TRAPD( err, GetProgramsByChannelIdL( aServiceProviderId, aChannelKey, 
+		   &programs ) ); 	
+	if ( err != KErrNone )
+		{
+		LIVE_TV_TRACE2(_L("GetProgramsByChannelIdL FAILED: %d"), err) ;
+		programs.ResetAndDestroy();
+		User::Leave( err );
+		}
+    TLinearOrder<CIptvEpgProgram> o( CIptvEpgProgram::LinearOrderOfProgramsById ); 
+	programs.Sort( o ); 
+
+	TBuf<KCustomSqlLength> sqlStatement;
+	sqlStatement.Append( _L("SELECT * FROM ") );
+	sqlStatement.Append( KIptvEpgScheduleTable );
+	sqlStatement.Append( _L(" WHERE ") );
+	sqlStatement.Append( KIptvEpgScheduleServiceProviderIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aServiceProviderId );
+	sqlStatement.Append( _L(" AND ") );	
+	sqlStatement.Append( KIptvEpgScheduleChannelIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aChannelKey );
+	sqlStatement.Append( _L(" AND ") );
+	sqlStatement.Append( KIptvEpgScheduleProgramIdCol );
+	sqlStatement.Append( _L(" = ") );
+	sqlStatement.AppendNum( aProgId );
+		
+    LIVE_TV_TRACE2(_L("query >%S<"), &sqlStatement);
+    
+	FetchSchedulesFromTableL( sqlStatement, aResultArray );
+	
+	const TInt c = aResultArray->Count(); 	
+
+	CIptvEpgProgram* programToUseForFinding = CIptvEpgProgram::NewL(); 
+	CleanupStack::PushL( programToUseForFinding ); 
+
+	TInt indexFound( KErrNotFound ); 
+	TInt64 programId( 0 );
+	for ( TInt i = 0; i < c; i ++ ) 
+		{
+		programId = ((*aResultArray)[i])->GetProgramId();
+		programToUseForFinding->SetProgramId( programId );
+		indexFound = programs.FindInOrder( programToUseForFinding, o ); 
+		if ( indexFound != KErrNotFound ) 
+			{
+			((*aResultArray)[i])->iProgram = programs[indexFound];
+			programs.Remove( indexFound );
+			}
+		}
+	programs.ResetAndDestroy();
+	CleanupStack::PopAndDestroy( programToUseForFinding );
+	CleanupStack::PopAndDestroy( &programs );
+	LIVE_TV_TRACE2(_L("GetSchedulesByProgIdL getting %d schedules"),c);
+    }
+
+// METHODS FOR LAST MODIFIED TABLE
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::GetLastModifiedDataL
+//
+// ---------------------------------------------------------------------------
+EXPORT_C void CIptvEpgDatabase::GetLastModifiedDataL( const TUint32 aServiceId,
+											 		  TDes& aETag,
+											 		  TDes& aLastModifiedDateTime )
+	{
+	LIVE_TV_TRACE1( _L("CIptvEpgDatabase::GetLastModifiedDataL IN") );
+	TBuf<KCustomSqlLength> sqlStatement;
+	sqlStatement.Append( _L("SELECT ") );
+	sqlStatement.Append( KIptvEpgLastModifiedTableETagCol );
+	sqlStatement.Append( _L(" , ") );
+	sqlStatement.Append( KIptvEpgLastModifiedTableTimeCol );
+	sqlStatement.Append( _L(" FROM ") );
+	sqlStatement.Append( KIptvEpgLastModifiedTable );
+	sqlStatement.Append( _L(" WHERE ") );
+	sqlStatement.Append( KIptvEpgLastModifiedTableServiceIdCol );
+	sqlStatement.Append( _L(" = " ) );
+	sqlStatement.AppendNum( aServiceId );
+
+	LIVE_TV_TRACE2( _L("SQL-statement = %S"), &sqlStatement );
+
+    RDbView view;
+    CleanupClosePushL( view );
+    TInt err( KErrNone );
+    err = view.Prepare( iMulticastDb, TDbQuery( sqlStatement ) );
+    LIVE_TV_TRACE2( _L("view.Prepare returned %d"), err );
+    if ( err != KErrNone )
+    	{
+    	User::Leave( err );
+    	}
+    err = view.EvaluateAll();
+    LIVE_TV_TRACE2( _L("view.EvaluateAll() returned %d"), err );
+    if ( err != KErrNone )
+    	{
+    	User::Leave( err );
+    	}
+    
+    
+    // Ownership of this pointer is now here. It needs to be deleted also
+    CDbColSet* lastModifiedColSet = view.ColSetL();
+    CleanupStack::PushL( lastModifiedColSet );
+    TInt lastModifiedDateTimeColNo = lastModifiedColSet->ColNo( KIptvEpgLastModifiedTableTimeCol );
+    TInt eTagColNo = lastModifiedColSet->ColNo( KIptvEpgLastModifiedTableETagCol );
+
+    // sql statement found a row from table,fetch that
+    if ( view.FirstL() )
+    	{
+		view.GetL();
+		
+		aLastModifiedDateTime = view.ColDes( lastModifiedDateTimeColNo );
+		aETag = view.ColDes( eTagColNo );
+		}
+	
+	CleanupStack::PopAndDestroy( lastModifiedColSet );
+    CleanupStack::PopAndDestroy( &view ); // closes view
+    LIVE_TV_TRACE3( _L("on return aETag = %S and aLastModifiedDateTime = %S"), &aETag, &aLastModifiedDateTime );
+	LIVE_TV_TRACE1( _L("CIptvEpgDatabase::GetLastModifiedDataL OUT") );
+	}
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::SetLastModifiedDataL
+//
+// ---------------------------------------------------------------------------
+EXPORT_C void CIptvEpgDatabase::SetLastModifiedDataL( const TUint32 aServiceId,
+													  const TDesC& aETag,
+													  const TDesC& aLastModifiedDateTime )
+	{
+	LIVE_TV_TRACE1( _L("CIptvEpgDatabase::SetLastModifiedDataL IN") );
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+
+	LIVE_TV_TRACE3( _L("aETag = %S, aLastModifiedDateTime = %S"), &aETag, &aLastModifiedDateTime );
+
+	// We can safely clear this because there is (or at least should) only one row
+	// in this table. This is because there is individual database for each and
+	// every service, one service has only one service address.
+	ClearLastModifiedTableL( aServiceId );
+
+	TBuf<KCustomSqlLength> sqlStatement;
+	sqlStatement.Append( _L("SELECT ") );
+	sqlStatement.Append( KIptvEpgLastModifiedTableServiceIdCol );
+	sqlStatement.Append( _L(" , ") );
+	sqlStatement.Append( KIptvEpgLastModifiedTableETagCol );
+	sqlStatement.Append( _L(" , ") );
+	sqlStatement.Append( KIptvEpgLastModifiedTableTimeCol );
+	sqlStatement.Append( _L(" FROM ") );
+	sqlStatement.Append( KIptvEpgLastModifiedTable );
+    RDbView view;
+    CleanupClosePushL( view );
+    User::LeaveIfError( view.Prepare( iMulticastDb,
+    					TDbQuery( sqlStatement ),
+    					TDbWindow::EUnlimited,
+    					RDbView::EInsertOnly ) );
+    view.InsertL();
+    
+    // Ownership of CDbColSet object is now here!
+	CDbColSet* lastModifiedColSet = view.ColSetL();
+    CleanupStack::PushL( lastModifiedColSet );
+
+    // Get the column numbers we need here
+    TInt servIdColNo = lastModifiedColSet->ColNo( KIptvEpgLastModifiedTableServiceIdCol );
+    TInt eTagColNo = lastModifiedColSet->ColNo( KIptvEpgLastModifiedTableETagCol );
+    TInt lastModifiedDateTimeCol = lastModifiedColSet->ColNo( KIptvEpgLastModifiedTableTimeCol );
+    
+    // Set values to the columns
+    view.SetColL( servIdColNo, aServiceId );
+    view.SetColL( eTagColNo, aETag );
+    view.SetColL( lastModifiedDateTimeCol, aLastModifiedDateTime );
+    
+    // Delete allocated object
+    CleanupStack::PopAndDestroy( lastModifiedColSet );
+    
+    // Commit changes to the database
+    view.PutL();
+    
+    CleanupStack::PopAndDestroy( &view );
+	LIVE_TV_TRACE1( _L("CIptvEpgDatabase::SetLastModifiedDataL OUT") );
+	}
+
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::ClearServiceEPGDataL
+//
+// ---------------------------------------------------------------------------
+EXPORT_C void CIptvEpgDatabase::ClearServiceEPGDataL( const TUint32 aServiceId )
+	{
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::ClearServiceEPGDataL in"));
+
+	if ( iLocalState == EBackup )
+		{
+		return;
+		}
+
+	ClearChannelTableL( aServiceId );
+
+	ClearProgramTableL( aServiceId );
+
+	ClearScheduleTableL( aServiceId );
+
+	ClearLatestEpgTableL( aServiceId );
+	
+	ClearLastModifiedTableL( aServiceId );
+
+	User::LeaveIfError( iMulticastDb.Compact() );
+	LIVE_TV_TRACE1(_L("CIptvEpgDatabase::ClearServiceEPGDataL out"));
+	}
+	
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::ChangeFileLockL
+//
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::ChangeFileLockL( const TDesC& aFileName, TFileLockFlags aFlags )
+	{
+	LIVE_TV_TRACE1( _L("CIptvEpgDatabase::ChangeFileLockL IN") );
+	if ( aFileName.Compare( iDbFile ) == 0 )
+		{
+		switch( aFlags )
+			{
+			case MBackupObserver::ETakeLock:
+			    {
+			    LIVE_TV_TRACE1( _L("aFlags = MBackupObserver::ETakeLock") );
+				CreateDbL();
+				CreateMulticastDbSessionL();    
+				iLocalState = EReady;
+				LIVE_TV_TRACE1( _L("Setting iLocalState to EReady") );
+				if ( iActiveWait->IsStarted() )
+					{
+					LIVE_TV_TRACE1( _L("Stopping iActiveWait") );
+					iActiveWait->AsyncStop();
+					}
+			    }
+				break;
+			case MBackupObserver::EReleaseLockNoAccess:
+			    {
+			    LIVE_TV_TRACE1( _L("aFlags = MBackupObserver::EReleaseLockNoAccess") );
+				CloseMulticastDbSession();
+				LIVE_TV_TRACE1( _L("Setting iLocalState to EBackup") );
+				iLocalState = EBackup;
+			    }
+				break;
+			default:
+				break;
+			}
+		}
+	LIVE_TV_TRACE1( _L("CIptvEpgDatabase::ChangeFileLockL OUT") );
+	}
+	
+// ---------------------------------------------------------------------------
+// CIptvEpgDatabase::CheckBackupStatus
+//
+// ---------------------------------------------------------------------------
+void CIptvEpgDatabase::CheckBackupStatus()
+	{
+	LIVE_TV_TRACE1( _L("CIptvEpgDatabase::CheckBackupStatus IN") );
+	if ( iLocalState == EBackup )
+		{
+		// Start waiting to see backup ending to continue.
+		if ( !iActiveWait->IsStarted() )
+			{
+			LIVE_TV_TRACE1( _L("iLocalState == EBackup -> starting active wait") );
+			iActiveWait->Start();	
+			}
+		else
+			{
+			LIVE_TV_TRACE1(_L("CIptvEpgDatabase::CheckBackupStatus: iActiveWait already started!"));
+			}
+		}
+	LIVE_TV_TRACE1( _L("CIptvEpgDatabase::CheckBackupStatus OUT") );
+	}
+
+//  End of File