dvrengine/CommonRecordingEngine/src/CCREngine.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:20:37 +0100
branchRCL_3
changeset 23 13a33d82ad98
parent 0 822a42b6c3f1
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201029 Kit: 201035

/*
* Copyright (c) 2007 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:    Engine part of the engine. In practice keeps count on*
*/




// INCLUDE FILES
#include <pathinfo.h>
#include "VideoServiceUtilsConf.hrh" 
#include "CCREngine.h"
#include "CCRStreamingSession.h"
#include "CCRSession.h"
#include "CCRClientInformer.h"
#include "CCRConnection.h"
#ifdef RD_IPTV_FEA_RTP_CLIP_SUPPORT
#include <ipvideo/CRtpUtil.h>
#include <ipvideo/CRtpClipHandler.h>
#endif // RD_IPTV_FEA_RTP_CLIP_SUPPORT
#include <e32msgqueue.h>
#include <ipvideo/CRTypeDefs.h>
#include <e32std.h>
#include <es_sock.h>
#include "videoserviceutilsLogger.h"

// CONSTANTS
const TUint KCRELoopbackPortStart( 1106 );

// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// CCREngine::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CCREngine* CCREngine::NewL( void )
    {
    CCREngine* self = new( ELeave ) CCREngine();

    // Use CleanupClosePushL to make sure the Close function defined in CObject
    // base class gets called. CObject will delete itself once its reference count
    // reaches zero. Using CleanupStack::PushL here results in E32USER-CBase panic 33
    // if there is a leave somewhere in construction
    CleanupClosePushL( *self );

    self->ConstructL();
    CleanupStack::Pop( self );
    return self;
    }

// -----------------------------------------------------------------------------
// CCREngine::CCREngine
// C++ default constructor can NOT contain any code, that might leave.
// -----------------------------------------------------------------------------
//
CCREngine::CCREngine( void ) : iLoopbackPort( KCRELoopbackPortStart )
    {
    // None
    }

// -----------------------------------------------------------------------------
// CCREngine::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
//
void CCREngine::ConstructL()
    {
    LOG( "CCREngine::ConstructL()" );
    
    // Note, quite high priority
    iCleanUp = new ( ELeave ) CAsyncCallBack( CActive::EPriorityStandard ); 
    }

// -----------------------------------------------------------------------------
// CCREngine::~CCREngine
// Destructor.
// -----------------------------------------------------------------------------
//
CCREngine::~CCREngine()
    {
    LOG( "CCREngine::~CCREngine()" );

    delete iCleanUp;
    iSessions.ResetAndDestroy();
    iSessionsToDelete.Reset(); 
    delete iConnection;
#ifdef RD_IPTV_FEA_RTP_CLIP_SUPPORT
    delete iClipHandler;
#endif // RD_IPTV_FEA_RTP_CLIP_SUPPORT
    iSockServer.Close(); 
    delete iInformer; 
    delete iQueueName;
    }

// -----------------------------------------------------------------------------
// Method for actual message handling.
//
// -----------------------------------------------------------------------------
//
void CCREngine::GeneralServiceL( const RMessage2& aMessage )
    {
#if defined( LIVE_TV_RDEBUG_TRACE ) || defined( LIVE_TV_FILE_TRACE )
    if ( aMessage.Function() != ECRGetPosition )
        {
        LOG1( "CCREngine::GeneralService(), aMessage: %d", aMessage.Function() );
        }
#endif // LIVE_TV_RDEBUG_TRACE || LIVE_TV_FILE_TRACE

    // Verify cababilities
    VerifyCapabilitiesL( aMessage );

    // Handle message
    TInt err( KErrNone );
    switch( aMessage.Function() )
        {
        case ECRSetIap:
            {
            TPckgBuf<SCRRtspIapParams> pckg;
            Read( aMessage, 0, pckg );
            err = SetConnectionId( pckg() );  
            aMessage.Complete( err );
            }
            break;      
            
        case ECRCancelSetIap:
            aMessage.Complete( CancelSetConnectionId() );
            break;
            
        case ECRPlayRtspUrl:
            {
            TPckgBuf<TUint> pckg0( 0 );
            TPckgBuf<SCRRtspParams> pckg1;
            Read( aMessage, 1, pckg1 );
            TRAP( err, pckg0() = PlayRtspUrlL( pckg1() ) );
            if ( !err )
                {
                Write( aMessage, 0, pckg0 );
                }
            aMessage.Complete( err );
            }
            break;      
            
        case ECRPlayDvbhLive:
            {
            TPckgBuf<TUint> pckg0( 0 );
            TPckgBuf<SCRLiveParams> pckg1;
            Read( aMessage, 1, pckg1 );
            TRAP( err, pckg0() = PlayDvbhLiveL( pckg1() ) );
            if ( !err )    
                {
                Write( aMessage, 0, pckg0 );
                }
            aMessage.Complete( err );
            }
            break;      
            
        case ECRChangeService:
            {
            TPckgBuf<TUint> pckg0( 0 );
            TPckgBuf<SCRLiveParams> pckg1;
            Read( aMessage, 0, pckg0 );
            Read( aMessage, 1, pckg1 );
            TRAP( err, pckg0() = ChangeDvbhServiceL( pckg0(), pckg1() ) );
            if ( !err )    
                {
                Write( aMessage, 0, pckg0 );
                }
            aMessage.Complete( err );
            }
            break;
            
        case ECRPlayRtpFile:
            {
            TPckgBuf<TUint> pckg0( 0 );
            TPckgBuf<SCRRtpPlayParams> pckg1;
            Read( aMessage, 1, pckg1 );
            TRAP( err, pckg0() = PlayRtpFileL( pckg1() ) );
            if ( !err )
                {
                Write( aMessage, 0, pckg0 );
                }
            aMessage.Complete( err );
            }
            break;      
            
        case ECRPlayRtpHandle:
            {
            RFile fileHandle;
            err = fileHandle.AdoptFromClient( aMessage, 1, 2 );
            if ( !err )
                {
                TPckgBuf<TUint> pckg( 0 );
                TRAP( err, pckg() = PlayRtpFileL( fileHandle ) );
                if ( !err )
                    {
                    Write( aMessage, 0, pckg );
                    }
                }
            fileHandle.Close();
            aMessage.Complete( err );
            }
            break;      
            
        case ECRRecordCurrentStream:
            {
            TPckgBuf<TUint> pckg0( 0 );
            Read( aMessage, 0, pckg0 );
            TPckgBuf<SCRRecordParams> pckg1;
            Read( aMessage, 1, pckg1 );
            TRAP( err, RecordCurrentStreamL( pckg0(), pckg1() ) );
            aMessage.Complete( err );
            }
            break;
            
        case ECRRecordRtspStream:
            {
            TPckgBuf<TUint> pckg0( 0 );
            TPckgBuf<SCRRtspParams> pckg1;
            Read( aMessage, 1, pckg1 );
            TPckgBuf<SCRRecordParams> pckg2;
            Read( aMessage, 2, pckg2 );
            TRAP( err, pckg0() = RecordRtspStreamL( pckg1(), pckg2() ) );
            aMessage.Complete( err );
            }
            break;
            
        case ECRRecordDvbhStream:
            {
            TPckgBuf<TUint> pckg0( 0 );
            TPckgBuf<SCRLiveParams> pckg1;
            Read( aMessage, 1, pckg1 );
            TPckgBuf<SCRRecordParams> pckg2;
            Read( aMessage, 2, pckg2 );
            TRAP( err, pckg0() = RecordDvbhStreamL( pckg1(), pckg2() ) );
            aMessage.Complete( err );
            }
            break;
            
        case ECRPauseRecordStream:
            {
            TPckgBuf<TUint> pckg0( 0 );
            Read( aMessage, 0, pckg0 );
            TPckgBuf<TBool> pckg1( 0 );
            Read( aMessage, 1, pckg1 );
            aMessage.Complete( PauseRecordStream( pckg0(), pckg1() ) );
            }
            break;
            
        case ECRStopRecordStream:
            {
            TPckgBuf<TUint> pckg0( 0 );
            Read( aMessage, 0, pckg0 );
            aMessage.Complete( StopRecordStream( pckg0() ) );
            }
            break;
            
        case ECRStartTimeShift:
            {
            TPckgBuf<TUint> pckg0( 0 );
            TPckgBuf<TUint> pckg1( 0 );
            Read( aMessage, 1, pckg1 );
            TRAP( err, pckg0() = StartTimeShiftL( pckg1() ) );
            if ( !err )
                {
                Write( aMessage, 0, pckg0 );
                }
            aMessage.Complete( err );
            }
            break;
            
        case ECRStopTimeShift:
            {
            TPckgBuf<TUint> pckg0( 0 );
            TPckgBuf<TUint> pckg1( 0 );
            Read( aMessage, 0, pckg0 );
            Read( aMessage, 1, pckg1 );
            aMessage.Complete( StopTimeShift( pckg0(), pckg1() ) );
            }
            break;
            
        case ECRPlayCommand:
            {
            TPckgBuf<TUint> pckg0( 0 );
            Read( aMessage, 0, pckg0 );
            TPckgBuf<TInt64> pckg1( 0 );
            Read( aMessage, 1, pckg1 );
            TPckgBuf<TInt64> pckg2( 0 );
            Read( aMessage, 2, pckg2 );
            aMessage.Complete( PlayCommand( pckg0(), pckg1(), pckg2() ) );
            }
            break;
        
        case ECRPauseCommand:
            {
            TPckgBuf<TUint> pckg0( 0 );
            Read( aMessage, 0, pckg0 );
            aMessage.Complete( PauseCommand( pckg0() ) );
            }
            break;
        
        case ECRStopCommand:
            {
            TPckgBuf<TUint> pckg0( 0 );
            Read( aMessage, 0, pckg0 );
            aMessage.Complete( StopCommand( pckg0() ) );
            }
            break;
        
        case ECRSetPosition:
            {
            TPckgBuf<TUint> pckg0( 0 );
            Read( aMessage, 0, pckg0 );
            TPckgBuf<TInt64> pckg1( 0 );
            Read( aMessage, 1, pckg1 );
            err = SetPosition( pckg0(), pckg1() );
            aMessage.Complete( err );
            }
            break;
        
        case ECRGetPosition:
            {
            TPckgBuf<TUint> pckg0( 0 );
            Read( aMessage, 0, pckg0 );
            TPckgBuf<TInt64> pckg1( 0 );
            Read( aMessage, 1, pckg1 );
            TPckgBuf<TInt64> pckg2( 0 );
            err = GetPosition( pckg0(), pckg1(), pckg2() );
            Write( aMessage, 1, pckg1 );
            Write( aMessage, 2, pckg2 );
            aMessage.Complete( err );
            }
            break;
            
        case ECRCloseSession:
            {
            TPckgBuf<TUint> pckg0( 0 );
            Read( aMessage, 0, pckg0 );
            aMessage.Complete( CloseSession( pckg0() ) );
            }
            break;
        
        case ECRPlayNullSource:
            {
            TPckgBuf<TUint> pckg0( 0 );
            TRAP( err, pckg0() = PlayNullSourceL() );
            Write( aMessage, 0, pckg0 );
            aMessage.Complete( err );
            }
            break;     
        
        case ECRPlayRtspUrlToNullSink:
            {
            TPckgBuf<TUint> pckg0( 0 );
            TPckgBuf<SCRRtspParams> pckg1;
            Read( aMessage, 1, pckg1 );
            TRAP( err, pckg0() = PlayRtspUrlToNullSinkL( pckg1() ) );
            Write( aMessage, 0, pckg0 );
            aMessage.Complete( err );
            }
            break;     
        
        default:
            aMessage.Complete( KErrNotSupported ); 
            break; 
        }
    }
    
//-----------------------------------------------------------------------------
// CCREngine::SessionStop()
// So, a session wants to quit. we can't just delete it here as return.
// Statement would then take us to deleted instance: put up a cleanup 
// CAsyncCallBack and return.
//-----------------------------------------------------------------------------
//
void CCREngine::SessionStop( CCRStreamingSession* aSession )
    {
    LOG1( "CCREngine::SessionStop(), Delete count: %d", iSessionsToDelete.Count() );    

    // InsertInAddressOrder checks for duplicate, if there is already
    // entry for that session, the array will remain unchanged
    TRAPD( err, iSessionsToDelete.InsertInAddressOrderL( aSession ) ); 
    if ( err )
        {
        LOG1( "CCREngine::SessionStop(), InsertInAddressOrder leaved: %d", err );      
        }

    // If not already active and sessions to delete?
    if ( !iCleanUp->IsActive() && iSessionsToDelete.Count() ) 
        {
        TCallBack cb( SessionStopCallBack, this );
        iCleanUp->Set( cb );
        iCleanUp->CallBack();
        }               
    }
    
// -----------------------------------------------------------------------------
// CCREngine::ConnectionStatusChange
//
// -----------------------------------------------------------------------------
//
void CCREngine::ConnectionStatusChange(
    TInt aSessionId,
    TCRConnectionStatus aStatus,
    TInt aErr )
    {
    LOG3( "CCREngine::ConnectionStatusChange(), aSessionId: %d, aStatus: %d, Error: %d",
                                                aSessionId, aStatus, aErr );
    
    SCRQueueEntry entry = { ECRMsgQueueConnectionError, KErrNone };
    entry.iSessionId = aSessionId;

    switch ( aStatus )
        {           
        case ECRConnectionError:
            {               
            entry.iMsg = ECRMsgQueueConnectionError;
            entry.iErr = aErr;
            }
            break;
        
        case ECRAuthenticationNeeded:
            {               
            entry.iMsg = ECRMsgQueueAuthenticationNeeded;
            entry.iErr = KErrNone;
            }      
            break;  
        
        case ECRNotEnoughBandwidth:
            {               
            entry.iMsg = ECRMsgQueueNotEnoughBandwidth;
            entry.iErr = KErrNone;
            }      
            break;  
        
        case ECRNormalEndOfStream:
            {               
            entry.iMsg = ECRMsgQueueNormalEndOfStream;
            entry.iErr = aErr;
            }
            break;
        
        case ECRAttachCompleted: // fall through
        case ECRSwitchingToTcp:
            {               
            aStatus == ECRAttachCompleted ? 
                           ( entry.iMsg = ECRMsgQueueAttachCompleted ) :
                           ( entry.iMsg = ECRMsgQueueSwitchingToTcp );
            
            if ( aErr == KErrNone )
                {
                // Releasing RSocket takes almost 40 seconds so we need 
                // to always use different port number, otherwise an  
                // "Already in use" error will be occurred.
                TTime now;
                now.UniversalTime();                  
                TInt port = KCRELoopbackPortStart + now.DateTime().Second();   
                iLoopbackPort == port ? ( iLoopbackPort = port + 1 ) : 
                                        ( iLoopbackPort = port );

                // Loopback port for VIA
                entry.iErr = iLoopbackPort;
                }
            else
                {
                entry.iErr = aErr;
                }
            }           
            break;  
            
        case ECRStreamIsLiveStream:
            {
            entry.iMsg = ECRMsgQueueStreamIsLiveStream; 
            entry.iErr = aErr; 
            }
            break; 

        case ECRStreamIsRealMedia:
            {
            entry.iMsg = ECRMsgQueueStreamIsRealMedia; 
            entry.iErr = aErr; 
            }
            break; 

        case ECRBearerChanged:
            {
            // Nobody is interested about this on the other side...
            return;         
            }

        case ECRTestSinkData:
            {
            entry.iMsg = ECRMsgQueueTestSinkData;
            entry.iErr = aErr;
            }
            break;

        case ECRSdpAvailable:
            {
            entry.iMsg = ECRMsgQueueSdpAvailable;
            entry.iErr = aErr;
            }
            break;
        
        case ECRReadyToSeek:
            {
            entry.iMsg = ECRMsgQueueReadyToSeek; 
            entry.iErr = aErr; 
            }
            break; 

        case ECRRecordingStarted:
            {
            entry.iMsg = ECRMsgQueueRecordingStarted;
            entry.iErr = aErr;
            }
            break;
        
        case ECRRecordingPaused:
            {
            entry.iMsg = ECRMsgQueueRecordingPaused;
            entry.iErr = aErr;
            }
            break;
        
        case ECRRecordingEnded:
            {
            entry.iMsg = ECRMsgQueueRecordingEnded;
            entry.iErr = aErr;
            }
            break;
        
        default:
            // None
            break;
        }
    
    if ( iQueueName && iInformer )
        {
        iInformer->SendMessage( iQueueName->Des(), entry ); 
        }
    }

// -----------------------------------------------------------------------------
// CCREngine::VerifyCapabilitiesL
// Checks capabilities of user of DVR API.
// -----------------------------------------------------------------------------
//
void CCREngine::VerifyCapabilitiesL( const RMessage2& aMessage )
    {
    if ( !aMessage.HasCapability( ECapabilityNetworkServices, 
         __PLATSEC_DIAGNOSTIC_STRING( "NetworkServices" ) ) )
        {
        LOG( "CCREngine::VerifyRbfCapabilitiesL(), Missing: NetworkServices !" );
        User::Leave( KErrPermissionDenied );
	    }
    
    if ( !aMessage.HasCapability( ECapabilityReadUserData,
         __PLATSEC_DIAGNOSTIC_STRING( "ReadUserData" ) ) )
	    {
        LOG( "CCREngine::VerifyRbfCapabilitiesL(), Missing: ReadUserData !" );
        User::Leave( KErrPermissionDenied );
	    }
                                 
    if ( !aMessage.HasCapability( ECapabilityWriteUserData,
         __PLATSEC_DIAGNOSTIC_STRING( "WriteUserData" ) ) )
	    {
        LOG( "CCREngine::VerifyRbfCapabilitiesL(), Missing: WriteUserData !" );
        User::Leave( KErrPermissionDenied );
	    }
    }

// -----------------------------------------------------------------------------
// CCREngine::SetConnectionId
//
// -----------------------------------------------------------------------------
//
TInt CCREngine::SetConnectionId( const SCRRtspIapParams& aIap ) 
    {
    LOG( "CCREngine::SetConnectionId() in" );

    TRAPD ( err, CreateConnectionL() ) ;
    if ( err == KErrNone )
        {
        delete iQueueName; iQueueName = NULL;
        TRAP( err, iQueueName = aIap.iQueueName.AllocL() );
        if ( err == KErrNone )
            {
            iConnection->Attach( aIap.iConnectionId );  
            }
        
        }
    LOG1( "CCREngine::SetConnectionId() out, err: %d", err );
    return err;
    }

// -----------------------------------------------------------------------------
// CCREngine::CancelSetConnectionId
//
// -----------------------------------------------------------------------------
//
TInt CCREngine::CancelSetConnectionId() 
    {
    LOG( "CCREngine::CancelSetConnectionId() in" );
    
    TInt err( KErrNone );
    if ( iConnection ) 
        {
        iSessions.ResetAndDestroy();
        delete iConnection; iConnection = NULL;
        iSockServer.Close(); 
        err = iSockServer.Connect( KESockDefaultMessageSlots * 3 );
        if ( err == KErrNone ) 
            {
            TRAP( err, iConnection = CCRConnection::NewL( iSockServer ) );
            if ( err == KErrNone && iConnection )
                {
                err = iConnection->RegisterObserver( this );                    
                }
            }
        }
    
    LOG1( "CCREngine::CancelSetConnectionId() out, err: %d", err );
    return err; 
    }

// -----------------------------------------------------------------------------
// CCREngine::PlayRtspUrlL
// Go through stream sessions and try to find if given url is already playing.
// If not, create new RTSP session and add sink to it.
// -----------------------------------------------------------------------------
//
TUint CCREngine::PlayRtspUrlL( const SCRRtspParams& aRtspParams ) 
    {
    LOG( "CCREngine::PlayRtspUrlL() in" );
    
    const TInt sessionIndex( VerifyRtspSessionL( aRtspParams ) );
    iSessions[sessionIndex]->CreateRtspSinkL( iLoopbackPort );
    TUint sessionChk( iSessions[sessionIndex]->SourceChecksum() );
    LOG1( "CCREngine::PlayRtspUrlL() out, sessionChk: %d", sessionChk );
    return sessionChk;
    }

// -----------------------------------------------------------------------------
// CCREngine::PlayDvbhLiveL
// Go through stream sessions and try to find if current service is already
// If not, create new DVB-H session and add sink to it.
// -----------------------------------------------------------------------------
//
TUint CCREngine::PlayDvbhLiveL( const SCRLiveParams& aLiveParams ) 
    {
    LOG( "CCREngine::PlayDvbhLiveL() in" );

    const TInt sessionIndex( VerifyDvbhSessionL( aLiveParams ) );
    iSessions[sessionIndex]->CreateXpsSinkL();
    iSessions[sessionIndex]->PostActionL();
    TUint sessionChk( iSessions[sessionIndex]->SourceChecksum() );
    LOG1( "CCREngine::PlayDvbhLiveL() out, sessionChk: %d", sessionChk );
    return sessionChk;
    }

// -----------------------------------------------------------------------------
// CCREngine::ChangeDvbhServiceL
// Go through stream sessions and try to find if current service is already
// If not, create new DVB-H session and add sink to it.
// -----------------------------------------------------------------------------
//
TUint CCREngine::ChangeDvbhServiceL(
    const TUint aSessionChk,
    const SCRLiveParams& aLiveParams ) 
    {
    LOG( "CCREngine::ChangeDvbhServiceL() in" );

    // Verify exist session
    const TInt currentSession( VerifySession( aSessionChk ) );
    User::LeaveIfError( currentSession );
    
    // Can't perform if recording or timeshift ongoing
    if ( iSessions[currentSession]->ClipHandlerUsed() )
        {
        User::Leave( KErrInUse );
        }

    // New session for new service
    const TInt sessionIndex( VerifyDvbhSessionL( aLiveParams ) );
    if ( sessionIndex == currentSession )
        {
        // Same service, no actions
        return aSessionChk;
        }
    
    // Stop sockets of DVB-H source (filters released)
    User::LeaveIfError( iSessions[currentSession]->StopCommand() );
    
    // Transfer ownership of existing XPS sink to a new session
    User::LeaveIfError( iSessions[currentSession]->TransferSink( 
        CCRStreamingSession::ECRXpsSinkId, *iSessions[sessionIndex] ) );
    iSessions[sessionIndex]->PostActionL();
    TUint sessionChk( iSessions[sessionIndex]->SourceChecksum() );
    
    // Delete existing unused session
    SessionStop( iSessions[currentSession] );
    LOG1( "CCREngine::ChangeDvbhServiceL() out, sessionChk: %d", sessionChk );
    return sessionChk;
    }

// -----------------------------------------------------------------------------
// CCREngine::PlayRtpFileL
//
// -----------------------------------------------------------------------------
//
TUint CCREngine::PlayRtpFileL( const SCRRtpPlayParams& aRtpParams ) 
    {
    LOG( "CCREngine::PlayRtpFileL() in" );

    const TInt sessionIndex( VerifyRtpFileSessionL( aRtpParams ) );
    iSessions[sessionIndex]->CreateXpsSinkL();
    iSessions[sessionIndex]->PostActionL();
    TUint sessionChk( iSessions[sessionIndex]->SourceChecksum() );
    LOG1( "CCREngine::PlayRtpFileL() out, sessionChk: %d", sessionChk );
    return sessionChk;
    }

// -----------------------------------------------------------------------------
// CCREngine::PlayRtpFileL
//
// -----------------------------------------------------------------------------
//
TUint CCREngine::PlayRtpFileL( const RFile& aFileHandle ) 
    {
    LOG( "CCREngine::PlayRtpFileL() in, with hadle" );

    TInt sessionIndex( VerifyRtpFileSessionL( aFileHandle ) );
    iSessions[sessionIndex]->CreateXpsSinkL();
    iSessions[sessionIndex]->PostActionL();
    TUint sessionChk( iSessions[sessionIndex]->SourceChecksum() );
    LOG1( "CCREngine::PlayRtpFileL() out, sessionChk: %d", sessionChk );
    return sessionChk;
    }

// -----------------------------------------------------------------------------
// CCREngine::RecordCurrentStreamL
//
// -----------------------------------------------------------------------------
//
void CCREngine::RecordCurrentStreamL(
    const TUint aSessionChk,
    const SCRRecordParams& aRecordParams ) 
    {
    LOG1( "CCREngine::StartRecordStreamL() in, aSessionChk: %d", aSessionChk );

    // Verify session
    const TInt sessionIndex( VerifySession( aSessionChk ) );
        
    // Session exist?
    if ( sessionIndex > KErrNotFound )
        {
        CreateRecordingSinkL( sessionIndex, aRecordParams );
        iSessions[sessionIndex]->PostActionL();
        }

    LOG1( "CCREngine::StartRecordStreamL() out, sessionIndex: %d", sessionIndex );
    }

// -----------------------------------------------------------------------------
// CCREngine::RecordRtspStreamL
//
// -----------------------------------------------------------------------------
//
TUint CCREngine::RecordRtspStreamL(
    const SCRRtspParams& aRtspParams,
    const SCRRecordParams& aRecordParams ) 
    {
    LOG( "CCREngine::RecordRtspStreamL() in" );

    // Verify session
    const TInt sessionIndex( VerifyRtspSessionL( aRtspParams ) );

    // Recording sink
    CreateRecordingSinkL( sessionIndex, aRecordParams );
    TUint sessionChk( iSessions[sessionIndex]->SourceChecksum() );
    LOG1( "CCREngine::RecordRtspStreamL() out, sessionChk: %d", sessionChk );
    return sessionChk;
    }

// -----------------------------------------------------------------------------
// CCREngine::RecordDvbhStreamL
//
// -----------------------------------------------------------------------------
//
TUint CCREngine::RecordDvbhStreamL(
    const SCRLiveParams& aLiveParams,
    const SCRRecordParams& aRecordParams ) 
    {
    LOG( "CCREngine::RecordDvbhStreamL() in" );

    // Verify session
    const TInt sessionIndex( VerifyDvbhSessionL( aLiveParams ) );

    // Recording sink
    CreateRecordingSinkL( sessionIndex, aRecordParams );
    iSessions[sessionIndex]->PostActionL();
    TUint sessionChk( iSessions[sessionIndex]->SourceChecksum() );
    LOG1( "CCREngine::RecordDvbhStreamL() out, sessionChk: %d", sessionChk );
    return sessionChk;
    }

// -----------------------------------------------------------------------------
// CCREngine::PauseRecordStream
//
// -----------------------------------------------------------------------------
//
TInt CCREngine::PauseRecordStream( const TUint aSessionChk, const TBool& aStart ) 
    {
    LOG2( "CCREngine::PauseRecordStream() in, aSessionChk: %d, aStart: %d", 
                                              aSessionChk, aStart );
    // Verify session
    const TInt sessionIndex( VerifySession( aSessionChk ) );
        
    // Session exist?
    if ( sessionIndex > KErrNotFound )
        {
        TInt err( KErrNone );
        if ( aStart )
            {
            // Clip format not known, so all types must try to pause
            err = iSessions[sessionIndex]->PauseCommand(
                  CCRStreamingSession::ECRRtpRecSinkId );
            if ( err == KErrCompletion )
                {
                err = iSessions[sessionIndex]->PauseCommand(
                      CCRStreamingSession::ECR3gpRecSinkId );
                }
            
            ConnectionStatusChange( aSessionChk, ECRRecordingPaused, err );
            }
        else
            {
            // Clip format not known, so all types must try to pause
            err = iSessions[sessionIndex]->RestoreCommand(
                  CCRStreamingSession::ECRRtpRecSinkId );
            if ( err == KErrCompletion )
                {
                err = iSessions[sessionIndex]->RestoreCommand(
                      CCRStreamingSession::ECR3gpRecSinkId );
                }

            ConnectionStatusChange( aSessionChk, ECRRecordingStarted, err );
            }
        
        LOG1( "CCREngine::PauseRecordStream() out, err: %d", err );
        return err;
        }
        
    LOG1( "CCREngine::PauseRecordStream() out, sessionIndex: %d", sessionIndex );
    return sessionIndex;    
    }

// -----------------------------------------------------------------------------
// CCREngine::StopRecordStream
//
// -----------------------------------------------------------------------------
//
TInt CCREngine::StopRecordStream( const TUint aSessionChk ) 
    {
    LOG1( "CCREngine::StopRecordStream() in, aSessionChk: %d", aSessionChk );
    
    // Verify session
    const TInt sessionIndex( VerifySession( aSessionChk ) );
        
    // Session exist?
    if ( sessionIndex > KErrNotFound )
        {
        // Clip format not known, so all types must try to stop
        iSessions[sessionIndex]->StopCommand(
            CCRStreamingSession::ECRRtpRecSinkId );
        iSessions[sessionIndex]->StopCommand(
            CCRStreamingSession::ECR3gpRecSinkId );
        // Possible error(s) ignored
        }
        
    LOG1( "CCREngine::StopRecordStream() out, sessionIndex: %d", sessionIndex );
    return sessionIndex;    
    }

// -----------------------------------------------------------------------------
// CCREngine::StartTimeShift
// Existing stream play will be splitted to two sessions. Existing source will
// be directed to recording and existing sink will get new source from playback.
// -----------------------------------------------------------------------------
//
TInt CCREngine::StartTimeShiftL( const TUint aSessionChk ) 
    {
    LOG1( "CCREngine::StartTimeShiftL() in, aSessionChk: %d", aSessionChk );

#ifdef RD_IPTV_FEA_RTP_CLIP_SUPPORT

    // Verify session
    const TInt currentSession( VerifySession( aSessionChk ) );
    User::LeaveIfError( currentSession );

    // Initial time shift clip name
    TPath initialName( KDvrTimeShiftFile );
    initialName.AppendNum( 0 );
    
    // RTP clip handler
    CreateClipHandlerL();

    // Start recording of stream
    SCRRecordParams recordParams;
    recordParams.iFileName.Set( initialName );
    recordParams.iFormat = ECRRecordTimeShift;
    iSessions[currentSession]->CreateRtpRecordSinkL( recordParams, iClipHandler );
    iSessions[currentSession]->PostActionL();

    // Create new session for time shift clip playback
    SCRRtpPlayParams params;
    params.iFileName = initialName;
    const TInt timeShiftSession( VerifyRtpFileSessionL( params ) );
    iSessions[timeShiftSession]->PostActionL();

    // Transfer ownership of existing XPS sink to a new session
    User::LeaveIfError( iSessions[currentSession]->TransferSink( 
        CCRStreamingSession::ECRXpsSinkId, *iSessions[timeShiftSession] ) );

    // Session checksum
    TUint sessionChk( iSessions[timeShiftSession]->SourceChecksum() );
    LOG1( "CCREngine::StartTimeShiftL() out, sessionChk: %d", sessionChk );
    return sessionChk;

#else // RD_IPTV_FEA_RTP_CLIP_SUPPORT
    ( void )aSessionChk;
    return KErrNotSupported;
#endif // RD_IPTV_FEA_RTP_CLIP_SUPPORT
    }

// -----------------------------------------------------------------------------
// CCREngine::StopTimeShift
// Streaming is set back to one session. Streaming orginal source stays and sink
// from temporary playback will be moved back to orginal session.
// -----------------------------------------------------------------------------
//
TInt CCREngine::StopTimeShift(
    const TUint aTimeShiftChk,
    const TUint aCurrentChk ) 
    {
    LOG2( "CCREngine::StopTimeShift() in, aTimeShiftChk: %d, aCurrentChk: %d", 
                                          aTimeShiftChk, aCurrentChk );
#ifdef RD_IPTV_FEA_RTP_CLIP_SUPPORT

    // Verify session
    int ret( KErrNotFound );
    const TInt currentSession( VerifySession( aCurrentChk ) );
    const TInt timeShiftSession( VerifySession( aTimeShiftChk ) );
        
    // Session exist?
    if ( currentSession > KErrNotFound && timeShiftSession > KErrNotFound )
        {
        // Stop time shift clip recording
        iSessions[currentSession]->StopCommand( 
            CCRStreamingSession::ECR3gpRecSinkId );
        
        // Stop time shift clip playback
        iSessions[timeShiftSession]->StopCommand();

        // Transfer ownership of existing XPS sink back to the old session
        ret = iSessions[timeShiftSession]->TransferSink( 
            CCRStreamingSession::ECRXpsSinkId, *iSessions[currentSession] );
        
        // Delete second session
        SessionStop( iSessions[timeShiftSession] );
        }
    
    // Clip handler not needed any longer
    DeleteClipHandler( currentSession );

    LOG1( "CCREngine::StopTimeShift() out, ret: %d", ret );
    return ret;    

#else // RD_IPTV_FEA_RTP_CLIP_SUPPORT
    ( void )aTimeShiftChk;
    ( void )aCurrentChk;
    return KErrNotSupported;
#endif // RD_IPTV_FEA_RTP_CLIP_SUPPORT
    }

// -----------------------------------------------------------------------------
// CCREngine::PlayCommand
//
// -----------------------------------------------------------------------------
//
TInt CCREngine::PlayCommand(
    const TUint aSessionChk,
    const TReal aStartPos,
    const TReal aEndPos ) 
    {
    LOG1( "CCREngine::PlayCommand(), aSessionChk: %d", aSessionChk );

    // Verify session
    const TInt sessionIndex( VerifySession( aSessionChk ) );
        
    // New session needed?
    if ( sessionIndex > KErrNotFound )
        {
        return iSessions[sessionIndex]->PlayCommand( aStartPos, aEndPos );
        }
        
    return KErrNotReady;
    }

// -----------------------------------------------------------------------------
// CCREngine::PauseCommand
//
// -----------------------------------------------------------------------------
//
TInt CCREngine::PauseCommand( const TUint aSessionChk )
    {
    LOG1( "CCREngine::PauseCommand(), aSessionChk: %d", aSessionChk );

    // Verify session
    const TInt sessionIndex( VerifySession( aSessionChk ) );
        
    // New session needed?
    if ( sessionIndex > KErrNotFound )
        {
        return iSessions[sessionIndex]->PauseCommand();
        }
        
    return KErrNotReady;
    }

// -----------------------------------------------------------------------------
// CCREngine::StopCommand
//
// -----------------------------------------------------------------------------
//
TInt CCREngine::StopCommand( const TUint aSessionChk )
    {
    LOG1( "CCREngine::StopCommand(), aSessionChk: %d", aSessionChk );

    // Verify session
    const TInt sessionIndex( VerifySession( aSessionChk ) );
        
    // New session needed?
    if ( sessionIndex > KErrNotFound )
        {
        return iSessions[sessionIndex]->StopCommand();
        }
        
    return KErrNotReady;
    }

// -----------------------------------------------------------------------------
// CCREngine::SetPosition
//
// -----------------------------------------------------------------------------
//
TInt CCREngine::SetPosition(
    const TUint aSessionChk,
    const TInt64 aPosition )
    {
    LOG1( "CCREngine::SetPosition(), aSessionChk: %d", aSessionChk );

    const TInt sessionIndex( VerifySession( aSessionChk ) );
    if ( sessionIndex > KErrNotFound )
        {
        return iSessions[sessionIndex]->SetPosition( aPosition );
        }
   
    return KErrNotReady;
    }

// -----------------------------------------------------------------------------
// CCREngine::GetPosition
//
// -----------------------------------------------------------------------------
//
TInt CCREngine::GetPosition(
    const TUint aSessionChk,
    TInt64& aPosition,
    TInt64& aDuration ) 
    {
    const TInt sessionIndex( VerifySession( aSessionChk ) );
    if ( sessionIndex > KErrNotFound )
        {
        return iSessions[sessionIndex]->GetPosition( aPosition, aDuration );
        }

    return KErrNotReady;
    }

// -----------------------------------------------------------------------------
// CCREngine::CloseSession
//
// -----------------------------------------------------------------------------
//
TInt CCREngine::CloseSession( const TUint aSessionChk )
    {
    LOG1( "CCREngine::CloseSession(), aSessionChk: %d", aSessionChk );
    
    // Verify session
    const TInt sessionIndex( VerifySession( aSessionChk ) );
    if ( sessionIndex > KErrNotFound )
        {
        SessionStop( iSessions[sessionIndex] );
        }
    
    return KErrNone;
    }
    
// -----------------------------------------------------------------------------
// CCREngine::PlayNullSourceL
//
// -----------------------------------------------------------------------------
//
TUint CCREngine::PlayNullSourceL() 
    {
    LOG( "CCREngine::PlayNullSourceL() in" );

    _LIT( KNullSourceClip, "NullSource.rtp" );
    TFileName nullSourcePath;
#if ( defined( __WINS__ ) || defined( __WINSCW__ ) )
    nullSourcePath = PathInfo::PhoneMemoryRootPath();
#else // __WINS__ || __WINSCW__
    nullSourcePath = PathInfo::MemoryCardRootPath();
#endif // __WINS__ || __WINSCW__
    nullSourcePath.Append( KNullSourceClip );

    TInt sessionIndex( VerifySession( nullSourcePath ) );
    if ( sessionIndex == KErrNotFound )
        {
        CCRStreamingSession* session = CCRStreamingSession::NewL(
                                       iSockServer, iConnection, *this );        
        CleanupStack::PushL( session );
        User::LeaveIfError( iSessions.Append( session ) );
        CleanupStack::Pop( session );

        // Only one source per session
        sessionIndex = iSessions.Count() - 1;
        iSessions[sessionIndex]->OpenSourceL( nullSourcePath );
        }

    iSessions[sessionIndex]->CreateXpsSinkL();
    //iSessions[sessionIndex]->CreateNullSinkL();
    iSessions[sessionIndex]->PostActionL();
    TUint sessionChk( iSessions[sessionIndex]->SourceChecksum() );
    LOG1( "CCREngine::PlayNullSourceL() out, sessionChk: %d", sessionChk );
    return sessionChk;
    }

// -----------------------------------------------------------------------------
// CCREngine::PlayRtspUrlToNullSinkL
//
// -----------------------------------------------------------------------------
//
TUint CCREngine::PlayRtspUrlToNullSinkL( const SCRRtspParams& aRtspParams ) 
    {
    LOG( "CCREngine::PlayRtspUrlToNullSinkL() in" );
    
    const TInt sessionIndex( VerifyRtspSessionL( aRtspParams ) );
    iSessions[sessionIndex]->CreateNullSinkL();
    TUint sessionChk( iSessions[sessionIndex]->SourceChecksum() );
    LOG1( "CCREngine::PlayRtspUrlToNullSinkL() out, sessionChk: %d", sessionChk );
    return sessionChk;
    }

// -----------------------------------------------------------------------------
// CCREngine::CreateConnectionL
// 
// -----------------------------------------------------------------------------
//
void CCREngine::CreateConnectionL( void )
    {
    LOG( "CCREngine::CreateConnectionL() in" );

    if ( iConnection == NULL )
        {
        User::LeaveIfError( iSockServer.Connect( KESockDefaultMessageSlots * 3 ) );
        iConnection = CCRConnection::NewL( iSockServer );
        User::LeaveIfError( iConnection->RegisterObserver( this ) );
        
        // Informer
        if ( iInformer == NULL )
            {
            iInformer = CCRClientInformer::NewL();
            }
        }
    
    LOG( "CCREngine::CreateConnectionL() out" );
    }

// -----------------------------------------------------------------------------
// CCREngine::CreateClipHandlerL
// 
// -----------------------------------------------------------------------------
//
void CCREngine::CreateClipHandlerL( void )
    {
    LOG1( "CCREngine::CreateClipHandlerL(), iClipHandler: %d", iClipHandler );

#ifdef RD_IPTV_FEA_RTP_CLIP_SUPPORT

    if ( !iClipHandler )
        {
        iClipHandler = CRtpClipHandler::NewL();
        }
#endif // RD_IPTV_FEA_RTP_CLIP_SUPPORT
    }

// -----------------------------------------------------------------------------
// CCREngine::VerifyRtspSessionL
// Go through stream sessions and try to find if RTSP stream is already playing.
// -----------------------------------------------------------------------------
//
TInt CCREngine::VerifyRtspSessionL( const SCRRtspParams& aRtspParams ) 
    {
    TInt sessionIndex( VerifySession( aRtspParams.iUrl ) );
    
    // New session needed?
    if ( sessionIndex == KErrNotFound )
        {
        CCRStreamingSession* session = CCRStreamingSession::NewL(
                                       iSockServer, iConnection, *this ); 
        CleanupStack::PushL( session );       
        User::LeaveIfError( iSessions.Append( session ) );
        CleanupStack::Pop( session );

        // Only one source per session
        sessionIndex = iSessions.Count() - 1;
        iSessions[sessionIndex]->OpenSourceL( aRtspParams, aRtspParams.iUrl );
        }
    
    User::LeaveIfError( sessionIndex );
    return sessionIndex;
    }

// -----------------------------------------------------------------------------
// CCREngine::VerifyDvbhSessionL
// Go through stream sessions and try to find if DVB-H live is already playing.
// -----------------------------------------------------------------------------
//
TInt CCREngine::VerifyDvbhSessionL( const SCRLiveParams& aLiveParams ) 
    {
    // Verify session
    HBufC* definition = HBufC::NewLC( aLiveParams.iSdpData.Length() );
    definition->Des().Copy( aLiveParams.iSdpData );
    TInt sessionIndex( VerifySession( *definition ) );

    // New session needed?
    if ( sessionIndex == KErrNotFound )
        {
        CCRStreamingSession* session = CCRStreamingSession::NewL(
                                       iSockServer, iConnection, *this );        
        CleanupStack::PushL( session );
        User::LeaveIfError( iSessions.Append( session ) );
        CleanupStack::Pop( session );
        
        // Only one source per session
        sessionIndex = iSessions.Count() - 1;
        iSessions[sessionIndex]->OpenSourceL( aLiveParams, *definition );
        }
    
    CleanupStack::PopAndDestroy( definition );
    User::LeaveIfError( sessionIndex );
    return sessionIndex;
    }

// -----------------------------------------------------------------------------
// CCREngine::VerifyRtpFileSessionL
// Go through stream sessions and try to find if RTP clip is already playing.
// -----------------------------------------------------------------------------
//
TInt CCREngine::VerifyRtpFileSessionL( const SCRRtpPlayParams& aRtpParams ) 
    {
#ifdef RD_IPTV_FEA_RTP_CLIP_SUPPORT

    // Verify session
    TInt sessionIndex( VerifySession( aRtpParams.iFileName ) );
        
    // New session needed?
    if ( sessionIndex == KErrNotFound )
        {
        
        CCRStreamingSession* session = CCRStreamingSession::NewL(
                                       iSockServer, iConnection, *this );        
        CleanupStack::PushL( session );
        User::LeaveIfError( iSessions.Append( session ) );
        CleanupStack::Pop( session );

        // RTP clip handler
        CreateClipHandlerL();
        
        // Only one source per session
        sessionIndex = iSessions.Count() - 1;
        iSessions[sessionIndex]->OpenSourceL( aRtpParams, iClipHandler, 
                                              aRtpParams.iFileName );
        }

    User::LeaveIfError( sessionIndex );
    return sessionIndex;

#else // RD_IPTV_FEA_RTP_CLIP_SUPPORT
    ( void )aRtpParams;
    return KErrNotSupported;
#endif // RD_IPTV_FEA_RTP_CLIP_SUPPORT
    }

// -----------------------------------------------------------------------------
// CCREngine::VerifyRtpFileSessionL
// Go through stream sessions and try to find if RTP clip is already playing.
// -----------------------------------------------------------------------------
//
TInt CCREngine::VerifyRtpFileSessionL( const RFile& aFileHandle ) 
    {
#ifdef RD_IPTV_FEA_RTP_CLIP_SUPPORT

    TFileName fileName( KNullDesC );
    aFileHandle.FullName( fileName );
    TInt sessionIndex( VerifySession( fileName ) );
        
    // New session needed?
    if ( sessionIndex == KErrNotFound )
        {
        CCRStreamingSession* session = CCRStreamingSession::NewL(
                                       iSockServer, iConnection, *this );        
        CleanupStack::PushL( session );
        User::LeaveIfError( iSessions.Append( session ) );
        CleanupStack::Pop( session );

        // RTP clip handler
        CreateClipHandlerL();
        
        // Only one source per session
        sessionIndex = iSessions.Count() - 1;
        iSessions[sessionIndex]->OpenSourceL( aFileHandle, iClipHandler, fileName );
        }

    User::LeaveIfError( sessionIndex );
    return sessionIndex;

#else // RD_IPTV_FEA_RTP_CLIP_SUPPORT
    ( void )aFileHandle;
    return KErrNotSupported;
#endif // RD_IPTV_FEA_RTP_CLIP_SUPPORT
    }

// -----------------------------------------------------------------------------
// CCREngine::VerifySession
// Go through stream sessions and try to find stream is already playing.
// -----------------------------------------------------------------------------
//
TInt CCREngine::VerifySession( const TDesC& aName ) 
    {
    if ( iSessions.Count() > 0 )
        {
        for ( TInt i( iSessions.Count() - 1 ); i >= 0; i-- )
            {
            const TUint chksm( iSessions[i]->SourceDefinition( aName ) );
            if ( chksm == iSessions[i]->SourceChecksum() )
                {
                return i;
                }
            }
        }

    return KErrNotFound;
    }

// -----------------------------------------------------------------------------
// CCREngine::VerifySession
// Go through stream sessions and try to find session index from active sessions.
// -----------------------------------------------------------------------------
//
TInt CCREngine::VerifySession( const TUint aSessionChk ) 
    {
    if ( iSessions.Count() > 0 )
        {
        for ( TInt i( iSessions.Count() - 1 ); i >= 0; i-- )
            {
            if ( aSessionChk == iSessions[i]->SourceChecksum() )
                {
                return i;
                }
            }
        }

    return KErrNotFound;
    }

//-----------------------------------------------------------------------------
// CCREngine::CreateRecordingSinkL
//
//-----------------------------------------------------------------------------
//
void CCREngine::CreateRecordingSinkL(
    const TInt aSessionIndex,
    const SCRRecordParams& aRecordParams )
    {
    LOG1( "CCREngine::CreateRecordingSinkL(), aSessionIndex: %d", aSessionIndex );
    
    User::LeaveIfError( aSessionIndex );
    switch ( aRecordParams.iFormat )
        {
#ifdef RD_IPTV_FEA_RTP_CLIP_SUPPORT
        case ECRRecordFormatRtp:
            // RTP clip handler
            CreateClipHandlerL();
            iSessions[aSessionIndex]->CreateRtpRecordSinkL(
                aRecordParams, iClipHandler );
            break;
#endif // RD_IPTV_FEA_RTP_CLIP_SUPPORT

        case ECRRecordFormat3gp:
            iSessions[aSessionIndex]->Create3gpRecordSinkL( aRecordParams );
            break;

        default:
            LOG( "CCREngine::CreateRecordingSinkL(), Clip format invalid !");
            User::Leave( KErrNotSupported );
            break;
        }
    }

//-----------------------------------------------------------------------------
// CCREngine::SessionStopCallBack
//
//-----------------------------------------------------------------------------
//
TInt CCREngine::SessionStopCallBack ( TAny* aThis ) 
    {
    LOG( "CCREngine::SessionStopCallBack()" );
    
    CCREngine* self = static_cast<CCREngine*>( aThis );
    self->DoSessionStop();
    return self->iSessionsToDelete.Count(); 
    }
    
//-----------------------------------------------------------------------------
// CCREngine::DoSessionStop
//
//-----------------------------------------------------------------------------
//
void CCREngine::DoSessionStop( void ) 
    {
    LOG1( "CCREngine::DoSessionStop() in, iSessionsToDelete.Count = %d", iSessionsToDelete.Count() );
    
    for ( TInt i( iSessionsToDelete.Count() - 1 ); i >= 0; i-- )
        {
        for ( TInt j( iSessions.Count() - 1 ); j >= 0; j-- )
            {
            if ( iSessions[j] == iSessionsToDelete[i] )
                {
                delete iSessions[j];
                iSessions.Remove( j ); 
                }
            }
        }
    
    // Supposed to be empty by now
    DeleteClipHandler( KErrNotFound );
    iSessionsToDelete.Reset();
    LOG( "CCREngine::DoSessionStop() out" );
    }
    
//-----------------------------------------------------------------------------
// CCREngine::DeleteClipHandler
//
//-----------------------------------------------------------------------------
//
void CCREngine::DeleteClipHandler( const TInt aCurrentSessionIndex ) 
    {
    LOG1( "CCREngine::DeleteClipHandler(), aCurrentSessionIndex: %d",
                                           aCurrentSessionIndex );
#ifdef RD_IPTV_FEA_RTP_CLIP_SUPPORT

    if ( iClipHandler )
        {
        // Find out clip handler usage
        TBool notUsed( ETrue );
        for ( TInt i( iSessions.Count() - 1 ); i >= 0; i-- )
            {
            if ( i != aCurrentSessionIndex && iSessions[i]->ClipHandlerUsed() )
                {
                notUsed = EFalse;
                }
            }

        // Clip handler not needed any longer?
        if ( notUsed )
            {
            delete iClipHandler; iClipHandler = NULL;    
            LOG( "CCREngine::DeleteClipHandler(), RTP ClipHandler deleted !" );
            }
        }
    
#else // RD_IPTV_FEA_RTP_CLIP_SUPPORT
    ( void )aCurrentSessionIndex;
#endif // RD_IPTV_FEA_RTP_CLIP_SUPPORT
    }
    
// -----------------------------------------------------------------------------
// CCREngine::Read
// Read from the client thread, if unsuccessful, panic the client.
// -----------------------------------------------------------------------------
//
void CCREngine::Read(
    const RMessage2& aMessage, 
    const TInt& aParam,
    TDes8& aDes ) 
    {
    TRAPD( err, aMessage.ReadL( aParam, aDes ) );
    if ( err )
        {
        PanicClient( ECRPanicBadDescriptor, aMessage );
        }
    }

// -----------------------------------------------------------------------------
// CCREngine::Read
// Read from the client thread, if unsuccessful, panic the client.
// -----------------------------------------------------------------------------
//
void CCREngine::Read(
    const RMessage2& aMessage, 
    const TInt& aParam,
    TDes16& aDes ) 
    {
    TRAPD( err, aMessage.ReadL( aParam, aDes ) );
    if ( err )
        {
        PanicClient( ECRPanicBadDescriptor, aMessage );
        }
    }

// -----------------------------------------------------------------------------
// CCREngine::Write
// Write to the client thread, if unsuccessful, panic the client.
// -----------------------------------------------------------------------------
//
void CCREngine::Write(
    const RMessage2& aMessage, 
    const TInt& aParam,
    const TDesC8& aDes ) 
    {
    TRAPD( err, aMessage.WriteL( aParam, aDes ) );
    if ( err )
        {
        PanicClient( ECRPanicBadDescriptor, aMessage );
        }
    }

// -----------------------------------------------------------------------------
// CCREngine::Write
// Write to the client thread, if unsuccessful, panic the client.
// -----------------------------------------------------------------------------
//
void CCREngine::Write(
    const RMessage2& aMessage, 
    const TInt& aParam,
    const TDesC16& aDes ) 
    {
    TRAPD( err, aMessage.WriteL( aParam, aDes ) );
    if ( err )
        {
        PanicClient( ECRPanicBadDescriptor, aMessage );
        }
    }

// -----------------------------------------------------------------------------
// CCREngine::PanicClient
//
// -----------------------------------------------------------------------------
//
void CCREngine::PanicClient( TInt aPanic, const RMessage2& aMessage )
    {
    // Panic the client on server side
    _LIT( KRbfClientFault, "Common recording engine" );
    aMessage.Panic( KRbfClientFault, aPanic );
    }   
    
//  End of File