/*
* 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:  Controller class for handling browser requests to play video
*
*/


// INCLUDE FILES
#include <mmf/common/mmferrors.h>
#include <aknclearer.h>
#include <AknUtils.h>

#include "BavpPlugin.h"
#include "BavpLogger.h"
#include "BavpControllerVideo.h"
#include "BavpView.h"
#include "BavpViewFullScreen.h"
#include <mmf/common/mmfcontrollerframework.h> 
#include <MMFScalingCustomCommandConstants.h>

using namespace RT_GestureHelper;

// CONSTANTS
// One second represented in microseconds
const TInt KBavpOneSecond = 1000000;

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

// -----------------------------------------------------------------------------
// CBavpControllerVideo::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
CBavpControllerVideo* CBavpControllerVideo::NewL( MBavpView* aView,
                                                  TUint aAccessPtId,
                                                  TBavpMediaType aMediaType,
                                                  const TDesC& aFileName )
    {
    CBavpControllerVideo* self = new( ELeave ) CBavpControllerVideo( aView, aAccessPtId );

    Log( EFalse, _L("CBavpControllerVideo::NewL this="), (TInt)self );

    CleanupStack::PushL( self );
    self->ConstructL( aMediaType, aFileName );
    CleanupStack::Pop( self );
    return self;
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::~CBavpControllerVideo()
// Destructor
// -----------------------------------------------------------------------------
CBavpControllerVideo::~CBavpControllerVideo()
    {
    Log( EFalse, _L("CBavpControllerVideo::~CBavpControllerVideo this="), (TInt)this );

    // If currently playing, call Stop before you close and delete
    if ( iCurrentState == EBavpPlaying && iVideoPlayer)
        {
        iVideoPlayer->Stop();
        }

    // Close the video plugin, and delete it
    if ( iVideoPlayer )
        {
        iVideoPlayer->Close();
        delete iVideoPlayer;
        }

    // CIdle AO used for display update
    if ( iDisplayUpdater )
        {
        delete iDisplayUpdater;
        }

  if ( iBackLightUpdater )
      {
      iBackLightUpdater->Cancel();
      delete iBackLightUpdater;
      }
    // Used for displaying content in full screen
    if ( iBavpViewFullScreen )
        {
        delete iBavpViewFullScreen;
        }
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::CBavpControllerVideo
// C++ default constructor can NOT contain any code, that
// might leave.
// -----------------------------------------------------------------------------
CBavpControllerVideo::CBavpControllerVideo( MBavpView* aView, TUint aAccessPtId )
    : CBavpController( aView, aAccessPtId )
    {
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::ConstructL
// Symbian 2nd phase constructor can leave.
// -----------------------------------------------------------------------------
void CBavpControllerVideo::ConstructL( TBavpMediaType aMediaType,
                                       const TDesC& aFileName )
    {
    // Construct the BavpController base class
    BaseConstructL( aMediaType, aFileName );

    // Create CIdle (AO) to update the display
    iDisplayUpdater = CIdle::NewL( CActive::EPriorityIdle );
    iBackLightUpdater=CHeartbeat::NewL(CActive::EPriorityStandard);
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::PrepareCompleteL
// Handle the leaving methods needed by MvpuoPrepareComplete
// -----------------------------------------------------------------------------
void CBavpControllerVideo::PrepareCompleteL()
    {
    // Resolution
    TSize size;
    iVideoPlayer->VideoFrameSizeL(size);
    iClipInfo->iResolutionHeight = size.iHeight;
    iClipInfo->iResolutionWidth = size.iWidth;

    // Bitrate
    iClipInfo->iBitrate = iVideoPlayer->VideoBitRateL() +
                          iVideoPlayer->AudioBitRateL();

    TInt iMetaCount = iVideoPlayer->NumberOfMetaDataEntriesL();
    CMMFMetaDataEntry* metaData = NULL;

    for ( TInt i = 0; i < iMetaCount; i++ )
        {
        metaData = iVideoPlayer->MetaDataEntryL( i );

        Log( EFalse, _L("metaData index="), i );
        Log( EFalse, metaData->Name() );
        Log( EFalse, metaData->Value() );

        // Check if seekable
        if ( !metaData->Name().CompareF( KBavpSeekable ) )
            {
            if ( !metaData->Value().CompareF( KBavpFalse ) )
                {
                iClipInfo->iSeekable = EFalse;
                }
            }

        // Check if live stream
        if ( !metaData->Name().CompareF( KBavpLiveStream ) )
            {
            if ( !metaData->Value().CompareF( KBavpTrue ) )
                {
                // Live stream is not seekable
                iClipInfo->iLiveStream = ETrue;
                iClipInfo->iSeekable = EFalse;
                }
            }

        delete metaData;
        }   // end of for

    // Set up the max volume
    iClipInfo->iMaxVolume = iVideoPlayer->MaxVolume();
    iPlayerMaxVolume = iClipInfo->iMaxVolume;

    // Duration
    iClipInfo->iDurationInSeconds = iVideoPlayer->DurationL();

    // Audio track
    iClipInfo->iAudioTrack = iVideoPlayer->AudioEnabledL();

    // Video track
    iClipInfo->iVideoTrack = iVideoPlayer->VideoBitRateL();

    if ( IsClipSeekable() )
        {
        iVideoPlayer->SetPositionL( iClipInfo->iPosition );
        }
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::InitVideoPlayer
// The non-leaving version that calls the leaving version. Closes the current
// player and prepares the MMF to play the video
// -----------------------------------------------------------------------------
void CBavpControllerVideo::InitVideoPlayer()
    {
    TRAP_IGNORE( InitVideoPlayerL() );
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::InitVideoPlayerL
// Closes the current player and prepares the MMF to play the video
// -----------------------------------------------------------------------------
void CBavpControllerVideo::InitVideoPlayerL()
    {
    Log( EFalse, _L("CBavpControllerVideo::InitVideoPlayerL()") );

    // If videoplayer is already opened, close and delete it
    if ( iVideoPlayer )
        {
        iVideoPlayer->Close();
        delete iVideoPlayer;
        iVideoPlayer = NULL;
        }

    // Get the rect to display
    TRect rect( iBavpView->CoeControl().Rect() );
    TPoint pt = iBavpView->WindowInst().AbsPosition();
    rect.Move( pt.iX, pt.iY );

    CEikonEnv* eikon = CEikonEnv::Static();
    RWsSession& ws = eikon->WsSession();
    CWsScreenDevice* screenDevice = eikon->ScreenDevice();

    // Clip rect manipulation.
    // Calculate the rect for display, including title and status pane
    TRect clipRect = GetClipRect( rect );

    Log( EFalse, _L("InitVideoPlayerL() - calling CVideoPlayerUtility::NewL") );

    // Initialize the videoplayer
    iVideoPlayer = CVideoPlayerUtility::NewL( *this, EMdaPriorityNormal,
                                              EMdaPriorityPreferenceNone,
                                              ws, *screenDevice,
                                              iBavpView->WindowInst(), rect,
                                              clipRect);

    // Register for loading notification
    iVideoPlayer->RegisterForVideoLoadingNotification( *this );

    switch ( iClipInfo->iMediaType )
        {
        case ELocalVideoFile:
            Log( EFalse, _L("InitVideoPlayerL() - calling OpenVideoFile") );
            OpenVideoFileL();
            break;

        case ELocalRamFile:
        case EUrl:
        case ELocalSdpFile:
#if defined(BRDO_ASX_FILE)
		case ELocalAsxFile:
#endif // BRDO_ASX_FILE
            Log( EFalse, _L("InitVideoPlayerL() - calling OpenVideoUrlL") );
            OpenVideoUrlL();
            break;

        // Not supported
        case ELocalAudioPlaylist:
        default:
            User::Leave( KErrNotSupported );
            break;
        }
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::UnInitVideoPlayer
// Closes the player and delete the instance
// -----------------------------------------------------------------------------
void CBavpControllerVideo::UnInitVideoPlayer()
    {
    Log( EFalse, _L("CBavpControllerVideo::UnInitVideoPlayer()") );

    if ( iVideoPlayer )
        {
        iVideoPlayer->Close();
        delete iVideoPlayer;
        iVideoPlayer = NULL;
        }

    iCurrentState = EBavpNone;
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::RotateScreen90
// Rotate the screen if needed
// -----------------------------------------------------------------------------
void CBavpControllerVideo::RotateScreen90()
    {
    Log( EFalse, _L("CBavpControllerVideo::RotateScreen90()") );

    TRect screenRect;
    AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EScreen, screenRect );

    // Rotate only if screen rect height is greater than its width
    if ( screenRect.Height() > screenRect.Width() )
        {
        TRAP_IGNORE( iVideoPlayer->SetRotationL( EVideoRotationClockwise90 ) );
        }
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::RevertToFullScreenL
// Set full screen display mode
// -----------------------------------------------------------------------------
void CBavpControllerVideo::RevertToFullScreenL()
    {
    Log( EFalse, _L("CBavpControllerVideo::RevertToFullScreenL()"));
    CBavpPluginEcomMain* npm = (CBavpPluginEcomMain*)Dll::Tls();
    bool fullscreen = true;
    
    iVideoPlayer->StopDirectScreenAccessL();
    iClipInfo->iInFullScreenMode = ETrue;

    npm->Funcs()->setvalue(iBavpView->bavPlugin()->getNPP(), 
                           NPPVpluginFullScreenBool, 
                           static_cast<void*>(&fullscreen));
    iBavpView->ControllerStateChangedL();
    
    CEikonEnv* eikon = CEikonEnv::Static();
    RWsSession& ws = eikon->WsSession();
    CWsScreenDevice* screenDevice = eikon->ScreenDevice();
    
    iNormalScreenRect = iBavpView->CoeControl().Rect();
    TPoint pt = iBavpView->WindowInst().AbsPosition();
    iNormalScreenRect.Move(pt.iX, pt.iY);
    TRect screenRect = eikon->EikAppUi()->ApplicationRect();
    
    CCoeControl* parentView = iBavpView->CoeControl().Parent();
    parentView->SetRect(screenRect);
    iBavpView->CoeControl().SetExtent(TPoint(0,0), screenRect.Size());
    
    iVideoPlayer->SetDisplayWindowL( ws, *screenDevice,
                                     iBavpView->WindowInst(),
                                     screenRect, screenRect );
                                         
    RotateScreen90();
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::RevertToNormalScreenL
// Set back to normal display mode
// -----------------------------------------------------------------------------
void CBavpControllerVideo::RevertToNormalScreenL()
    {
     Log( EFalse, _L("CBavpControllerVideo::RevertToNormalScreenL()") );
    CEikonEnv* eikon = CEikonEnv::Static();
    RWsSession& ws = eikon->WsSession();
    CWsScreenDevice* screenDevice = eikon->ScreenDevice();
    CBavpPluginEcomMain* npm = (CBavpPluginEcomMain*)Dll::Tls();
    bool fullscreen = false;
    
    iVideoPlayer->StopDirectScreenAccessL();
    
    npm->Funcs()->setvalue(iBavpView->bavPlugin()->getNPP(), 
                               NPPVpluginFullScreenBool, 
                               static_cast<void*>(&fullscreen));

    CCoeControl* parentView = iBavpView->CoeControl().Parent();
    parentView->SetRect(iNormalScreenRect);
    iBavpView->CoeControl().SetExtent(TPoint(0,0), iNormalScreenRect.Size());

    iClipInfo->iInFullScreenMode = EFalse;
    RefreshRectCoordinatesL();
    iVideoPlayer->SetRotationL( EVideoRotationNone );
    iBavpView->ControllerStateChangedL();
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::ToggleScreen
// Start a call back for the display screen switches (Full Screen to
// Normal Screen)
// -----------------------------------------------------------------------------
void CBavpControllerVideo::ToggleScreen()
    {
    if ( iDisplayUpdater->IsActive() )
        {
        iDisplayUpdater->Cancel();
        }

    iDisplayUpdater->Start( TCallBack( CBavpControllerVideo::WaitForScreenSwitch,
                                       this ) );
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::RefreshRectCoordinatesL
// Refresh the coordinates of rect for display
// -----------------------------------------------------------------------------
void CBavpControllerVideo::RefreshRectCoordinatesL()
    {
    Log( EFalse, _L("CBavpControllerVideo::RefreshRectCoordinatesL()") );

    if ( IsClipFullScreen() ) {
        return;
    }
    if ( iVideoPlayer )
        {
        TRect rect( iBavpView->CoeControl().Rect() );

        TRect wr(iBavpView->WindowRect()); //can have negative coordinates 
                                           //if video scrolled out of viewport
        // Windows' absolute position, relative to the current screen
        TPoint pt = iBavpView->WindowInst().AbsPosition();
        rect.Move( pt.iX, pt.iY );
        wr.Move( pt.iX, pt.iY );


        CEikonEnv* eikon = CEikonEnv::Static();
        RWsSession& ws = eikon->WsSession();
        CWsScreenDevice* screenDevice = eikon->ScreenDevice();

        // Reset clipRect
        TRect clipRect = rect;
        clipRect = GetClipRect( rect );

        Log( EFalse, _L("\nPosition: == clipRect to DAS:  ==\n") );
        Log( EFalse, _L("\nPosition:: clipRect.x = \n"), clipRect.iTl.iX );
        Log( EFalse, _L("\nPosition:: clipRect.y = \n"), clipRect.iTl.iY );
        Log( EFalse, _L("\nPosition:2: clipRect.x = \n"), clipRect.iBr.iX );
        Log( EFalse, _L("\nPosition:2: clipRect.y = \n"), clipRect.iBr.iY );

		TRAP_IGNORE
		    (
              iVideoPlayer->SetDisplayWindowL( ws, *screenDevice,
            							     iBavpView->WindowInst(),
            							     wr, clipRect );
		    );
    if( iCurrentState == EBavpPaused || iCurrentState == EBavpStopped || iCurrentState == EBavpPlayComplete )
        {
        iVideoPlayer->RefreshFrameL();
        }
        }
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::WaitForScreenSwitch
// Switches between normal screen and full screen
// -----------------------------------------------------------------------------
TInt CBavpControllerVideo::WaitForScreenSwitch( TAny* aThisData )
    {
    TRAP_IGNORE( WaitForScreenSwitchL( aThisData ) );
    return KErrNone;
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::WaitForScreenSwitch
// Switches between normal screen and full screen
// -----------------------------------------------------------------------------
void CBavpControllerVideo::WaitForScreenSwitchL( TAny* aThisData )
    {
    Log( EFalse, _L("CBavpControllerVideo::WaitForScreenSwitchL()") );

    // Use static cast
    CBavpControllerVideo* thisData = STATIC_CAST(CBavpControllerVideo*, aThisData);

    // Switch from Normal screen mode to Full Screen mode
    if ( !thisData->IsClipFullScreen() )
        {
        thisData->RevertToFullScreenL();
     
        }
    else if ( thisData->IsClipFullScreen() )
        {
        // Switch from Full Screen mode to Normal Screen mode
        thisData->RevertToNormalScreenL();
     
        }
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::DoFastForwardL
// Fast forwards the video
// -----------------------------------------------------------------------------
TInt CBavpControllerVideo::DoFastForwardL( TAny* aThisData )
    {
    CBavpControllerVideo* thisData = STATIC_CAST( CBavpControllerVideo*, aThisData );
    TTimeIntervalMicroSeconds skipPosition( 0 );
    TTimeIntervalMicroSeconds currentPosition( thisData->iVideoPlayer->PositionL() );

    Log( EFalse, _L("CBavpControllerVideo::DoFastForwardL() - currentPosition = "),
         currentPosition.Int64() );

    // If we're not at the end of clip, skip forward a few positions
    if ( currentPosition < thisData->iClipInfo->iDurationInSeconds )
        {
        skipPosition = currentPosition.Int64() + KSkipToPosition;

        // If skip pass end of clip, set to the end of clip
        if ( skipPosition > thisData->iClipInfo->iDurationInSeconds )
            {
            skipPosition = thisData->iClipInfo->iDurationInSeconds;
            }

        Log( EFalse, _L("CBavpControllerVideo::DoFastForwardL() - skipPosition = "),
             skipPosition.Int64() );

        // Set the position
        thisData->iVideoPlayer->SetPositionL( skipPosition );

        // Refresh the frame
        thisData->iVideoPlayer->RefreshFrameL();
        thisData->iClipInfo->iPosition = skipPosition;
        }
    else
        {
        // Fast Forward reached the end of the clip, cancel the fast forward
        thisData->iPositionUpdater->Cancel();
        thisData->iClipInfo->iPosition = thisData->iClipInfo->iDurationInSeconds;
        // Set the state to complete since it reached the end of the clip
        thisData->iCurrentState = EBavpFastForwardComplete;
        Log( EFalse, _L("CBavpControllerVideo::DoFastForwardL() - End of clip") );
        }

    return ETrue;
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::DoRewindL
// Rewinds the video
// -----------------------------------------------------------------------------
TInt CBavpControllerVideo::DoRewindL( TAny* aThisData )
    {
    CBavpControllerVideo* thisData = STATIC_CAST( CBavpControllerVideo*, aThisData );
    TTimeIntervalMicroSeconds skipPosition( 0 );
    TTimeIntervalMicroSeconds currentPosition( thisData->iVideoPlayer->PositionL() );

    Log( EFalse, _L("CBavpControllerVideo::DoFastForwardL() - currentPosition = "),
         currentPosition.Int64() );

    // We're not at the beginning of the clip, rewind a few positions
    if ( currentPosition > 0 )
        {
        skipPosition = currentPosition.Int64() - KSkipToPosition;

        // If skip pass beginning of clip, set to the beginning of clip
        if ( skipPosition < 0 )
            {
            skipPosition = 0;
            }

        Log( EFalse, _L("CBavpControllerVideo::RewindL() - skipPosition = "),
             skipPosition.Int64() );

        // Set the position
        thisData->iVideoPlayer->SetPositionL( skipPosition );

        // Refresh the frame
        thisData->iVideoPlayer->RefreshFrameL();
        thisData->iClipInfo->iPosition = skipPosition;
        }
    else
        {
        // Rewind reached the beginning of the clip, cancel the rewind
        thisData->iPositionUpdater->Cancel();
        thisData->iClipInfo->iPosition = 0;
        // Set the state to complete since it reached beginning of clip
        thisData->iCurrentState = EBavpRewindComplete;
        Log( EFalse, _L("CBavpControllerVideo::RewindL() - beginning of clip") );
        }

    return ETrue;
    }

// --------------------------------------------------------------------------
// CBavpControllerVideo::HandleError
// Handle error codes. We can receive errors from the MMF Video Player
// and its MMF callbacks (mvpuoPlayComplete, etc).
// The MMF errors are for handling content issues, such as decoding content
// and network access.
// NOTES:
// MMF errors start at -12000, see /epoc32/include/mmf/common/MMFErrors.h
// MMF also returns -1 (KErrNotFound) and few other system-wide errors
// -----------------------------------------------------------------------------
void CBavpControllerVideo::HandleError( TInt aError )
    {
    Log( EFalse, _L("In CBavpControllerVideo::HandleError(): err="), aError );

    switch ( aError )
        {
        case KErrSessionClosed: // When we stop live streaming
            if ( iCurrentState == EBavpBuffering ||
                 iCurrentState == EBavpStopped )
                {
                Log( EFalse, _L("HandleError: iCurrentState=Buffering or Stopped and err=KErrSessionClosed") );
                // Controller needs to be re-initialized, whenever
                // live streaming is "Stopped"
                // iCurrentState = EBavpNone, set by UnInitVideoPlayer
                UnInitVideoPlayer();
                // Set state to stopped, because we "stop" live content
                iCurrentState = EBavpStopped;
                }
            else if ( iCurrentState == EBavpPlaying ||
                      iCurrentState == EBavpPaused )
                {
                Log( EFalse, _L("HandleError:iCurrentState=Playing or Paused and err=KErrSessionClosed") );
                // If the window is not on top, it might be a video or phone
                // call interrupt
                TRAP_IGNORE
                    (
                    if ( !iBavpView->IsTopWindowL() )
                        {
                        InitVideoPlayer();
                        }
                    )   // end of TRAP_IGNORE
                }
            else
                {
                }
            break;

        case KErrDisconnected:
            // If the window is not on top, it might be a video or phone
            // call interrupt
            Log( EFalse, _L("HandleError: err=KErrDisconnected") );
            TRAP_IGNORE
                (
                if ( !iBavpView->IsTopWindowL() )
                    {
                    InitVideoPlayer();
                    }
                )   // end of TRAP_IGNORE
            break;

        case KErrMMVideoDevice:
        case KErrMMAudioDevice:
            HandleMultiInstanceError();
            break;

        // Errors from MMF (i.e. MvpuoPrepareComplete, MvpuoPlayComplete...)
        case KErrNotFound:
        case KErrNotSupported:
        case KErrCorrupt:
        case KErrInUse:
        case KErrNoMemory:
        case KErrAbort:
        case KErrArgument:
        case KErrCouldNotConnect:
        case KErrTimedOut:
        case KErrHardwareNotAvailable:
        case KErrOverflow:
        case KErrMMNotEnoughBandwidth:
        case KErrMMNetworkRead:
        case KErrMMNetworkWrite:
        case KErrMMServerNotSupported:
        case KErrMMUDPReceive:
        case KErrMMInvalidProtocol:
        case KErrMMInvalidURL:
        case KErrMMProxyServer:
        case KErrMMDecoder:
        case KErrMMPartialPlayback:
            // Close the player and delete player instance.
            // iCurrentState = EBavpNone, set by UnInitVideoPlayer.
            UnInitVideoPlayer();

            // Display we have bad content
            Log( EFalse, _L("HandleError: state=BadContent") );
            iCurrentState = EBavpBadContent;
            iBavpView->UpdateView();
            break;

        default:
            // Do nothing
            break;

        }   // end of switch

    Log( EFalse, _L("Out CBavpControllerVideo::HandleError()") );
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::HandleKeysL
// Handles user key presses when we're Activated (aka Top of CCoeControl stack)
// -----------------------------------------------------------------------------
TKeyResponse CBavpControllerVideo::HandleKeysL( const TKeyEvent& aKeyEvent,
                                                TEventCode aType )
    {
    TKeyResponse keyResponse( EKeyWasNotConsumed );

    // If we're in full screen mode, and any key is pressed, toggle to normal
    // screen. Consume all key presses (down, key, up) when in full screen mode.
    if ( IsClipFullScreen() )
        {
        if ( aType == EEventKeyDown )
            {
            ToggleScreen();
            }
        keyResponse = EKeyWasConsumed;
        }
    else
        {
        // Use the default HandleKeysL method
        keyResponse = CBavpController::HandleKeysL( aKeyEvent, aType );
        }

    return keyResponse;
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::HandleCommandL
// Default implementation, override as needed.
// Handles the commands from the Option Menu defined in TBavpCommandIds
// -----------------------------------------------------------------------------
void CBavpControllerVideo::HandleCommandL( TBavpCommandIds aCommand )
    {
    Log( EFalse, _L("CBavpControllerVideo::HandleCommandL(): aCommand="), (TInt)aCommand );

    switch ( aCommand )
        {
        case EBavpCmdPlayFullScreen:
            ToggleScreen();
            break;

        default:
            // Use the default HandleCommandL method
            CBavpController::HandleCommandL( aCommand );
            break;
        }
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::PlayAudioVideoL
// Handles request to open and play an audio or video content
// -----------------------------------------------------------------------------
void CBavpControllerVideo::PlayAudioVideoL()
    {
    Log( EFalse, _L("CBavpControllerVideo::PlayAudioVideoL() ") );

    if ( iClipInfo->iMediaType == ELocalRamFile )
        {
        ParseRamFileL();
        }
#if defined(BRDO_ASX_FILE)
    else if ( iClipInfo->iMediaType == ELocalAsxFile )
        {
        ParseAsxFileL();
        }
#endif // BRDO_ASX_FILE
    // Check for the mediatype and open the file
    InitVideoPlayerL();
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::Stop
// Stops video from playing, if playing.
// -----------------------------------------------------------------------------
void CBavpControllerVideo::Stop()
    {
    Log( EFalse, _L("CBavpControllerVideo::Stop") );

    // If we are fast forwarding or rewind, stop the position updater
    iPositionUpdater->Cancel();

    if ( iVideoPlayer )
        {
        // Stop video and set the state to stop
        iVideoPlayer->Stop();
        iCurrentState = EBavpStopped;

        iClipInfo->iPosition = 0;
        TRAP_IGNORE
            (
            iVideoPlayer->SetPositionL( iClipInfo->iPosition );
            iVideoPlayer->RefreshFrameL();
            );
        }

    // The videoPlayer can play audio-only content, so we need to updateDisplay
    // to show the audio stop animation
    if ( !IsClipVideo() )
        {
        iBavpView->UpdateView();
        }
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::PlayL
// Plays video
//
// NOTE: The MMF throws an error when interrupted by a telephone call, so
// iCurrentState=EBavpBadContent and PlayL called after call is done.
// -----------------------------------------------------------------------------
void CBavpControllerVideo::PlayL()
    {
    Log( EFalse, _L("CBavpControllerVideo::PlayL") );

    if ( !iVideoPlayer || !iPlayerInitialized )
        {
        // 1) Live-stream clip that was stopped will close the iVideoPlayer and
        // need buffering, because Play() will have to be reinitialized with
        // server.
        // 2) The initialization of multiple video instances and a single
        // playback hardware/software (ie Julie H/W) will cause the second plus
        // instances to return an error. HandleError() will display stop animation,
        // and if the user selects PlayL(), and the iVideoPlayer needs to be
        // reinitialized.
        //
        // The buffering animation will be stopped, when MvpuoPrepareComplete()
        // is called.
        iCurrentState = EBavpBuffering;
        iBavpView->UpdateView();
        Log( EFalse, _L("PlayL - Calling InitVideoPlayerL()") );

        // This calls OpenUrlL or OpenFileL, which will call iVideoPlayer->Play
        InitVideoPlayerL();
        return;
        }

    if ( iCurrentState == EBavpPaused ||
         iCurrentState == EBavpFastForwarding ||
         iCurrentState == EBavpRewinding )
        {
        // If we are fast forwarding or rewind, pause
        if ( iPositionUpdater->IsActive() )
            {
            // PauseL stops the PositionUpdater
            PauseL();
            }

        // We are resuming play and the clip is seekable, get the last
        // position and adjust the last position, if needed
        if ( iClipInfo->iPosition >=
             iClipInfo->iDurationInSeconds.Int64() - KBavpOneSecond )
            {
            // Take back one second if too near end of clip
            TTimeIntervalMicroSeconds adjustPosition =
                iClipInfo->iPosition.Int64() - KBavpOneSecond;

            // Negative value is not allowed, use beginning of clip
            if ( adjustPosition.Int64() < 0 )
                {
                adjustPosition = 0;
                }

            // Use the adjusted position
            iClipInfo->iPosition = adjustPosition;
            }
        }
    else
        {
        // Handle all other states, EBavpStopped, EBavpPlayComplete,
        // EBavpRewindComplete, EBavpFastForwardComplete, EBavpBadContent
        iClipInfo->iPosition = 0;
        }

    if ( IsClipOnDemand() && iCurrentState == EBavpStopped )
        {
        // On-demand that was stopped will need buffering,
        // because Play() will have to be reinitialized with server.
        // The buffering animation is stopped, for on-demand when
        // MvloLoadingComplete() is called
        iCurrentState = EBavpBuffering;
        Log( EFalse, _L("PlayL - Set EBavpBuffering") );
        }
    else
        {
        // Set state and update view to stop any animations running
        iCurrentState = EBavpPlaying;
        Log( EFalse, _L("PlayL - Set EBavpPlaying") );
        }

    iBavpView->UpdateView();

    iVideoPlayer->SetPositionL( iClipInfo->iPosition );
    iVideoPlayer->Play();
  // ETwelveOClock: Timer tick is on the second - from Symbian
  if (!iBackLightUpdater->IsActive())
    {
    iBackLightUpdater->Start( ETwelveOClock, this );
    }
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::PauseL
// Pauses video while playing. Saves the last position, if seekable content.
// -----------------------------------------------------------------------------
void CBavpControllerVideo::PauseL()
    {
    Log( EFalse, _L("CBavpControllerVideo::PauseL") );

    // If the position updater is running, stop it
    iPositionUpdater->Cancel();

    if ( iVideoPlayer )
        {
    //disable screensaver
    iBackLightUpdater->Cancel();
        if ( IsClipSeekable() )
            {
            // Seekable content, save position for possible resume
            iVideoPlayer->PauseL();
            iClipInfo->iPosition = iVideoPlayer->PositionL();
            iCurrentState = EBavpPaused;
            }
        else
            {
            // Not seekable content, i.e. Live stream
            iVideoPlayer->Stop();
            iClipInfo->iPosition = 0;
            iVideoPlayer->SetPositionL( iClipInfo->iPosition );
            iCurrentState = EBavpStopped;
            }
        }
    // The videoPlayer can play audio-only content, so we need to updateDisplay
    // to show the audio paused animation
    if ( !IsClipVideo() )
        {
        iBavpView->UpdateView();
        }
    }

// -----------------------------------------------------------------------------
// CBavpControllerAudio::FastForwardL
// Fast forwards the video. This is only called on seekable and local file
// content.
// -----------------------------------------------------------------------------
void CBavpControllerVideo::FastForwardL()
    {
    // Check that the content can be Fast Forwarded, this is used when media key
    // is pressed. We don't allow the user to select FF from Option Menu, if this
    // condition is not already meet.
    if ( !IsClipSeekable() && !IsClipLocalMedia() )
        {
        return;
        }

    // If playing, pause it (PauseL stops the PositionUpdater)
    if ( iCurrentState == EBavpPlaying )
        {
        PauseL();
        }

    iCurrentState = EBavpFastForwarding;
    iPositionUpdater->Start( KInitialDelay, KUpdateFrequency,
                             TCallBack( &DoFastForwardL, this ) );
  if (!iBackLightUpdater->IsActive())
    {
    iBackLightUpdater->Start( ETwelveOClock, this );
    }
    }

// -----------------------------------------------------------------------------
// CBavpControllerAudio::RewindL
// Rewinds the video. This is only called on seekable and local file
// content.
// -----------------------------------------------------------------------------
void CBavpControllerVideo::RewindL()
    {
    // Check that the content can be Rewound, this is used when media key
    // is pressed. We don't allow the user to select FF from Option Menu, if this
    // condition is not already meet.
    if ( !IsClipSeekable() && !IsClipLocalMedia() )
        {
        return;
        }

    // If playing, pause it (PauseL stops the PositionUpdater)
    if ( iCurrentState == EBavpPlaying )
        {
        PauseL();
        }

    iCurrentState = EBavpRewinding;
    iPositionUpdater->Start( KInitialDelay, KUpdateFrequency,
                             TCallBack( &DoRewindL, this ) );
  if (!iBackLightUpdater->IsActive())
    {
    iBackLightUpdater->Start( ETwelveOClock, this );
    }

    }
// -----------------------------------------------------------------------------
// CBavpControllerVideo::OpenVideoUrlL
// Handles request to open the url link
// -----------------------------------------------------------------------------
void CBavpControllerVideo::OpenVideoUrlL()
    {
    Log( EFalse, _L("CBavpControllerVideo::OpenUrlL() entered") );

    // Note: Play() is called from MvpuoPrepareComplete()
    iVideoPlayer->OpenUrlL( *iClipInfo->iUrl, iAccessPtId,
                            KNullDesC8, KRopControllerUid );
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::OpenVideoFileL
// Open a video file
// -----------------------------------------------------------------------------
void CBavpControllerVideo::OpenVideoFileL()
    {
    Log( EFalse, _L("CBavpControllerVideo::OpenFileL() ") );

    // Note: Play() is called from MvpuoPrepareComplete()
    iVideoPlayer->OpenFileL( *iClipInfo->iFileName );
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::SetPlayerVolume
// -----------------------------------------------------------------------------
void CBavpControllerVideo::SetPlayerVolume( TInt aVolume )
    {
    if ( iVideoPlayer && iPlayerInitialized )
        {
        // The CR volume is 0-10, convert to Video player volume 0-100
        TInt playerVolume = ( aVolume * iPlayerMaxVolume ) / KCRVolumeMax;

        // Set Video player volume
        TRAP_IGNORE( iVideoPlayer->SetVolumeL( playerVolume) );
        }
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::GetPlayerVolume
// -----------------------------------------------------------------------------
TInt CBavpControllerVideo::GetPlayerVolume()
    {
    TInt playerVolume( 0 );
    TInt CRVolume( 0 );

    if ( iVideoPlayer && iPlayerInitialized )
        {
        // Video player returns 0-100
        playerVolume = iVideoPlayer->Volume();

        // Convert to CR volume 0-10
        CRVolume = ( playerVolume * KCRVolumeMax ) / iPlayerMaxVolume;
        }

    return CRVolume;
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::MvpuoOpenComplete
// Notification to the client that the opening of the video clip has completed,
// successfully, or otherwise.
// -----------------------------------------------------------------------------
void CBavpControllerVideo::MvpuoOpenComplete( TInt aError )
    {
    Log( EFalse, _L("MvpuoOpenComplete err="), aError );

    if ( aError != KErrNone )
        {
        // Got an error from the MMF callback
        HandleError( aError );
        }
    else
        {
        // No error opening player, proceed with preparing player
        iVideoPlayer->Prepare();
        }
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::MvpuoPrepareComplete
// Notification to the client that the opening of the video clip has been prepared
// successfully, or otherwise.
// This callback is called in response to a call to CVideoPlayerUtility::Prepare().
// -----------------------------------------------------------------------------
void CBavpControllerVideo::MvpuoPrepareComplete( TInt aError )
    {
    Log( EFalse, _L("MvpuoPrepareComplete err="), aError );

    if ( aError != KErrNone )
        {
        HandleError( aError );
        }
    else
        {
        // Proceed with initialization and playing content

        // Video player initialized and ready for interaction,
        // volume, option menus, etc...
        iPlayerInitialized = ETrue;

        // Cleanup clip info
        iClipInfo->ReInit();

        // Handle all of the leaving methods of preparing the clip and
        // controller. Reading meta data, max volume, ...
        TRAP_IGNORE( PrepareCompleteL() );

        // Full screen display mode, rotate if necessary
        if ( IsClipFullScreen() )
            {
            RotateScreen90();
            }

        // Use the iCurrrentVolume, everytime we "set" the volume in the
        // BavpController we check for Profile setting, so we can use it here
        SetPlayerVolume( iCurrentVolume );

        // Start to play this media object
        iVideoPlayer->Play();

        // Stop the buffering animation now, to avoid screen flicker
        iCurrentState = EBavpPlaying;
        iBavpView->UpdateView();
        }
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::MvpuoPlayComplete
// Notification that video playback has completed. This is not called if playback
// is explicitly stopped by calling Stop.
// -----------------------------------------------------------------------------
void CBavpControllerVideo::MvpuoPlayComplete( TInt aError )
    {
    Log( EFalse, _L("MvpuoPlayComplete err="), aError );

    if ( aError != KErrNone )
        {
        // Got an error from the MMF callback
        HandleError( aError );
        }
    else
        {
        // No error, proceed with playing complete
        iCurrentState = EBavpPlayComplete;
        iClipInfo->iPosition = 0;

        // Set the previous call state to complete, this will ensure we
        // don't try to replay the content if a call comes in
        iPreCallState = EBavpPlayComplete;

        // Revert back to normal screen if it's full screen display
        if ( IsClipFullScreen() )
            {
            TRAP_IGNORE
                (
                RevertToNormalScreenL();
                iBavpView->ControllerStateChangedL();
                );
            }

        iBavpView->UpdateView();
        }
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::MvpuoEvent
// General event notification from controller. These events are specified by the
// supplier of the controller. Take the user initiaiated event, like selecting
// "pause" from the menu item, or another MMF event and convert into a
// "video plugin error", so we can process in HandleError().
// -----------------------------------------------------------------------------
void CBavpControllerVideo::MvpuoEvent( const TMMFEvent& aEvent )
    {
    Log( EFalse, _L("MvpuoEvent aEvent.iErrorCode="), aEvent.iErrorCode );

    if ( aEvent.iEventType == KMMFEventCategoryVideoPlayerGeneralError )
        {
        HandleError( aEvent.iErrorCode );
        }
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::MvloLoadingComplete
// Notification that video clip loading/rebuffering has started
// -----------------------------------------------------------------------------
void CBavpControllerVideo::MvloLoadingStarted()
    {
    Log( EFalse, _L("MvloLoadingStarted") );

    if ( iCurrentState !=  EBavpPlaying )
        {
        // Start the buffering animation
        iCurrentState = EBavpBuffering;
        iBavpView->UpdateView();
        }
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::MvloLoadingComplete
// Notification that video clip loading/rebuffering has completed
// and starting to play
// -----------------------------------------------------------------------------
void CBavpControllerVideo::MvloLoadingComplete()
    {
    Log( EFalse, _L("MvloLoadingComplete") );

  if ( !iBackLightUpdater->IsActive() )
    {
    iBackLightUpdater->Start( ETwelveOClock, this );
    }
    // Stop the buffering animation
    iCurrentState = EBavpPlaying;
    iBavpView->UpdateView();
    }

 // -----------------------------------------------------------------------------
// CBavpControllerVideo::getPositionL
// To get the current position of the clip
// -----------------------------------------------------------------------------

 TTimeIntervalMicroSeconds CBavpControllerVideo::getPositionL()
    {
    if ( iVideoPlayer )
    {
        return iVideoPlayer->PositionL();
    }
    return NULL;
    }

 // -----------------------------------------------------------------------------
// CBavpControllerVideo::setPositionL
// To set the position of the clip
// -----------------------------------------------------------------------------

  void CBavpControllerVideo::setPositionL(TTimeIntervalMicroSeconds val)
    {
        if ( iVideoPlayer )
        {
            if ( !IsClipSeekable() && !IsClipLocalMedia() )
            {
                return;
            }

            TBool didWePause = EFalse;
            // If playing, pause it (PauseL stops the PositionUpdater)
            if ( iCurrentState == EBavpPlaying )
            {
                PauseL();
                didWePause = ETrue;
            }

            if ( (val > iClipInfo->iDurationInSeconds ) || (val < 0) )
            {
                val = 0;
            }

            iVideoPlayer->SetPositionL(val);
            iVideoPlayer->RefreshFrameL();
            iClipInfo->iPosition = val;
            if ( didWePause )
            {
                PlayL();
            }
        }
    }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::Beat
// Call HandleScreenSaver
// -----------------------------------------------------------------------------
//
void CBavpControllerVideo::Beat()
  {
  HandleScreenSaver();
  }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::Synchronize
// Call HandleScreenSaver
// -----------------------------------------------------------------------------
//
void CBavpControllerVideo::Synchronize()
  {
  HandleScreenSaver();
  }

// -----------------------------------------------------------------------------
// CBavpControllerVideo::HandleScreenSaver
// To disable backlight for screensaver if needed
// -----------------------------------------------------------------------------
//
void CBavpControllerVideo::HandleScreenSaver()
{
   Log( EFalse, _L("CBavpControllerVideo::HandleScreenSaver() entered" ));

    //disable screensaver when it's in playing|forwarding|backwarding mode
    if ( NoScreenSaverMode() && iVideoPlayer )
      {
      User::ResetInactivityTime();
      }
}

TBool CBavpControllerVideo::NoScreenSaverMode()
{
  return (iCurrentState == EBavpPlaying ||
        iCurrentState == EBavpFastForwarding ||
        iCurrentState == EBavpRewinding);
}


// -----------------------------------------------------------------------------
// CBavpControllerVideo::SetDefaultAspectRatioL
// Sets default aspect ratio (code is taken from mmplayer)
// -----------------------------------------------------------------------------
/*
 * This function was added for consistency with mmplayer.
 * Not used is 5.0 (tube) since we want to preserve correct 
 * aspect ratio and this function will stretch the video to
 * the full screen, which due to tube screen size doesn't match
 * to correct ratio.
 * If needed it should be called in  WaitForScreenSwitchL() after 
 * screen mode changed.
 */
void CBavpControllerVideo::SetDefaultAspectRatioL()
{
  TSize frameSize;
  TRect rect = iBavpView->CoeControl().Rect(); 
  
  if ( iVideoPlayer ) {

    iVideoPlayer->VideoFrameSizeL( frameSize );
  }

  if ( frameSize.iWidth > 0 && frameSize.iHeight > 0) {
 
    TMMFScalingType scalingType = EMMFNatural;
 
    TReal32 videoAspectRatio = (TReal)frameSize.iWidth /
                                (TReal)frameSize.iHeight;
    TReal32 dispAspectRatio = (TReal)rect.Width() / (TReal)rect.Height(); 
 
 // Choose the scaling type through the rule:
 // videoAspectRatio - iDisplayAspectRatio > 0.1 ==> zoom
 // videoAspectRatio - iDisplayAspectRatio < 0.1 ==> stretch
 // videoAspectRatio = iDisplayAspectRatio ==> natural
     if ( videoAspectRatio - dispAspectRatio > 0.1 ) {
       scalingType = EMMFZoom;
     }
     else if ( videoAspectRatio != dispAspectRatio ) {
       scalingType = EMMFStretch;
     }

     TMMFMessageDestinationPckg destinationPckg(KUidInterfaceMMFControllerScalingMsg );
      
     TPckgBuf<TInt> scaleTypePckg( scalingType );
     
     iVideoPlayer->CustomCommandSync( destinationPckg,
                                       EMMFSetScalingType,
                                       scaleTypePckg,
                                       KNullDesC8 );
     iVideoPlayer->RefreshFrameL();

   }
}

void CBavpControllerVideo::HandleInComingCallL()

{
	if ( IsClipFullScreen() )
      {
      RevertToNormalScreenL();
      iBavpView->ControllerStateChangedL();
      }	
}

// -----------------------------------------------------------------------------
// CBavpControllerVideo::HandleGesture
// -----------------------------------------------------------------------------
TBool CBavpControllerVideo::HandleGesture(TGestureEvent *gesture)
{
    TBool ret = EFalse;
    TGestureCode gtype =  gesture->Code(EAxisBoth); 
    switch(gtype)
        {
        case EGestureTap:
            {
                if (IsClipFullScreen())
                    {
                    ToggleScreen();
                    ret = ETrue;
                    }
                break;
            }
        }
    return ret;
}
//  End of File
