browserplugins/browseraudiovideoplugin/src/BavpController.cpp
changeset 0 84ad3b177aa3
child 15 e45c3f40ea5f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/browserplugins/browseraudiovideoplugin/src/BavpController.cpp	Mon Mar 30 12:49:49 2009 +0300
@@ -0,0 +1,869 @@
+/*
+* 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:  Base Controller class for handling browser requests to play
+*                audio or video
+*
+*/
+
+
+// INCLUDE FILES
+#include <bautils.h>
+#include <f32file.h>
+#include <utf.h>
+#include <e32cmn.h>
+#include <aknquerydialog.h>                 // Volume list query dialog
+#include <aknlists.h>
+#include <CTSYDomainPSKeys.h>
+
+#include <BrowserUiSDKCRKeys.h>
+#include <BrowserAudioVideoPlugin.rsg>
+
+#include "BavpController.h"
+#include "BavpClipInfo.h"
+#include "BavpView.h"
+#include "BavpLogger.h"
+
+#if defined(BRDO_ASX_FF)
+#include "AsxParser.h"
+#endif //BRDO_ASX_FF
+
+#include "eikon.hrh"
+
+
+// CONSTANTS
+const TInt KBavpMaxLinkFileSize = 5120; // 5kB
+const TInt KRectPadding = 2;
+
+// Define our static BavpController array
+RPointerArray<CBavpController> CBavpController::iBavpControllerArray;
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CBavpController::CBavpController
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+CBavpController::CBavpController( MBavpView* aView,
+                                  TUint aAccessPtId )
+    : CActive( EPriorityStandard ),
+      iCurrentState( EBavpNone ),
+      iPreCallState( EBavpNone ),
+      iLastCommand( EBavpCmdUnknown ),
+      iLoopCount( 1 ),
+      iInitLoopCount( 1 ),
+      iInfiniteLoopFlag( EFalse ),
+      iAccessPtId( aAccessPtId ),
+      iBavpView( aView ),
+      iOriginalFileName ( NULL ),
+      iMimeType ( NULL )
+    {
+        CActiveScheduler::Add( this );
+    }
+
+// -----------------------------------------------------------------------------
+// CBavpController::~CBavpController()
+// Destructor
+// -----------------------------------------------------------------------------
+CBavpController::~CBavpController()
+    {
+    Log( EFalse, _L("CBavpController::~CBavpController this="), (TInt)this );
+
+    if ( iClipInfo )
+        {
+        delete iClipInfo;
+        }
+
+    iIncomingCalls.Close();
+
+    // Cancel active object and deleting removes from the ActiveScheduler
+    Cancel();
+
+    if ( iBavpVolumeHandler )
+        {
+        delete iBavpVolumeHandler;
+        }
+
+    // No need to check, if not active, Cancel() does nothing
+    if ( iPositionUpdater )
+        {
+        iPositionUpdater->Cancel();
+        delete iPositionUpdater;
+        }
+
+    if ( iHwKeyEvents )
+        {
+        delete iHwKeyEvents;
+        }
+
+     if ( iOriginalFileName )
+     {
+        delete iOriginalFileName;
+     }
+
+     if ( iMimeType )
+     {
+        delete iMimeType;
+     }
+
+    // Remove this instance from the array
+    TInt index = iBavpControllerArray.Find( this );
+    if ( index != KErrNotFound )
+        {
+        iBavpControllerArray.Remove( index );
+        }
+    if ( iBavpControllerArray.Count() == 0 )
+        {
+        iBavpControllerArray.Close();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CBavpController::HandleBrowserNotification
+// Default implementation, override as needed.
+// Handles notification from the Browser concerning the Browser's focus state
+// (Browser is in-focus, out-focus, foreground, or the background application)
+// and if this plugin is in-focus or out-focus. If the Browser is out-focus,
+// this plugin (all plugins) are out-focus. This is not used currently,
+// because we do not react to the Browser changing focus. We historically would
+// stop playing audio when the browser's focus changed (including when option
+// menu is popped up, ie menu top of stack).
+// -----------------------------------------------------------------------------
+void CBavpController::HandleBrowserNotification( TBool aFocus )
+    {
+    Log( EFalse, _L("CBavpController::HandleBrowserNotification: aBrowserFocus="),
+            aFocus );
+    }
+
+// -----------------------------------------------------------------------------
+// CBavpController::HandleError
+// Default implementation, override as needed.
+// This default error handling implementation just displays the broken (bad)
+// content animation and sets state to EBavpBadContent.
+// -----------------------------------------------------------------------------
+void CBavpController::HandleError( TInt aError )
+    {
+    Log( EFalse, _L("CBavpController::HandleError(): aError="), aError );
+
+    if ( aError != KErrNone )
+        {
+        // Any error, display we have bad content
+        iCurrentState = EBavpBadContent;
+        iBavpView->UpdateView();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CBavpController::HandleKeysL
+// Default implementation, override as needed.
+// Handles user key presses when the Plugin is Activated.
+// -----------------------------------------------------------------------------
+TKeyResponse CBavpController::HandleKeysL( const TKeyEvent& aKeyEvent,
+                                           TEventCode /*aType*/ )
+    {
+    Log( EFalse, _L("CBavpController::HandleKeysL()") );
+
+    TKeyResponse keyResponse = EKeyWasNotConsumed;
+
+    switch ( aKeyEvent.iCode )
+        {
+        // Cancel key (RSK) was pressed
+        case EKeyDevice1:
+            // Return the focus to the Browser, remove it from Bavp
+            iBavpView->CoeControl().SetFocus( EFalse );
+            keyResponse = EKeyWasConsumed;
+            break;
+
+        // Arrow keys was pressed
+        case EKeyUpArrow:             // North
+
+        case EKeyRightUpArrow:        // Northeast
+        case EStdKeyDevice11:         // Extra KeyEvent supports diagonal event simulator wedge
+
+        case EKeyRightArrow:          // East
+
+        case EKeyRightDownArrow:      // Southeast
+        case EStdKeyDevice12:         // Extra KeyEvent supports diagonal event simulator wedge
+
+        case EKeyDownArrow:           // South
+
+        case EKeyLeftDownArrow:       // Southwest
+        case EStdKeyDevice13:         // Extra KeyEvent supports diagonal event simulator wedge
+
+        case EKeyLeftArrow:           // West
+
+        case EKeyLeftUpArrow:         // Northwest
+        case EStdKeyDevice10:         // Extra KeyEvent supports diagonal event simulator wedge
+
+            // Do nothing with these keys, there is no navigating inside Bavp.
+            keyResponse = EKeyWasConsumed;
+            break;
+
+        default:
+        // Do nothing, let the rest of the key events pass back not consumed
+        break;
+        }   // end of switch
+
+    return keyResponse;
+    }
+
+// -----------------------------------------------------------------------------
+// CBavpController::HandleCommandL
+// Default implementation, override as needed.
+// Handles the commands from the Option Menu defined in TBavpCommandIds
+// -----------------------------------------------------------------------------
+void CBavpController::HandleCommandL( TBavpCommandIds aCommand )
+    {
+    Log( EFalse, _L("CBavpController::HandleCommandL(): aCommand="), (TInt)aCommand );
+
+    switch ( aCommand )
+        {
+        case EBavpCmdPlay:
+            iLastCommand = EBavpCmdPlay;
+            PlayL();
+            break;
+
+        case EBavpCmdStop:
+            iLastCommand = EBavpCmdStop;
+            Stop();
+            break;
+
+        case EBavpCmdPause:
+            iLastCommand = EBavpCmdPause;
+            PauseL();
+            break;
+
+        case EBavpCmdFastForward:
+            iLastCommand = EBavpCmdFastForward;
+            FastForwardL();
+            break;
+
+        case EBavpCmdRewind:
+            iLastCommand = EBavpCmdRewind;
+            RewindL();
+            break;
+
+        case EBavpCmdChangeVolume:
+            iLastCommand = EBavpCmdChangeVolume;
+            CreateVolumeListDlgL();
+            break;
+
+        case EBavpCmdMuteVolume:
+            iLastCommand = EBavpCmdMuteVolume;
+            iBavpVolumeHandler->HandleNotifyInt( KBrowserMediaVolumeControl,
+                                                 KCRVolumeMute );
+            break;
+
+        default:
+            iLastCommand = EBavpCmdUnknown;
+            break;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CBavpController::BavpGainedFocus
+// Default implementation, override as needed.
+// Called by CBavpView to CBavpPlugin whenever Bavp Plugin has focus and soft key
+// cancel is hit. When this happens the Browser calls NotifyL with 1.
+// -----------------------------------------------------------------------------
+void CBavpController::BavpFocusChanged( TBool aFocus )
+    {
+    iBavpHasFocus = aFocus;
+    }
+
+// -----------------------------------------------------------------------------
+// CBavpController::SetVolumeFromAttribute
+// Provides CBavpController with the volume attribute from the tags on the
+// HTTP page, i.e. <object volume="high"...
+// -----------------------------------------------------------------------------
+void CBavpController::SetVolumeFromAttribute( TInt aAttributeVolume )
+    {
+    // Use the lower volume:
+    // 1) Current volume (iCurrentVolume)
+    // 2) Volume setting on web page (aAttributeVolume)
+    if ( aAttributeVolume < iCurrentVolume )
+        {
+        iCurrentVolume = aAttributeVolume;
+        iBavpVolumeHandler->HandleNotifyInt( KBrowserMediaVolumeControl,
+                                             iCurrentVolume );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CBavpController::SetLoopFromAttribute
+// Provides CBavpController with the loop attribute from the tags on the
+// HTTP page, i.e. <object loop="infinite"... or <object loop="4"...
+// -----------------------------------------------------------------------------
+void CBavpController::SetLoopFromAttribute( TInt aLoopValue, TBool aInfiniteFlag )
+    {
+    // Save the loop count, already checked for valid range
+    iLoopCount = aLoopValue;
+
+    // Save the initial loop count, in case we get an error while looping
+    // through the content
+    iInitLoopCount = iLoopCount;
+
+    // If the loop value is set to "infinite" looping. We currently use
+    // a max loop of 50 for infinite
+    iInfiniteLoopFlag = aInfiniteFlag;
+}
+
+// -----------------------------------------------------------------------------
+// CBavpControllerAudioo::RefreshRectCoordinates
+// Refresh the coordinates of rect for display
+// -----------------------------------------------------------------------------
+void CBavpController::RefreshRectCoordinates()
+    {
+    Log( EFalse, _L("CBavpController::RefreshRectCoordinates()") );
+    }
+
+// -----------------------------------------------------------------------------
+// CBavpController::ParseRamFileL
+// Read the ram file and parse the the url, put into iClipInfo->iUrl
+// -----------------------------------------------------------------------------
+void CBavpController::ParseRamFileL()
+    {
+    Log( EFalse, _L("CBavpController::ParseRamFileL() ") );
+
+    RFs rFs;
+    RFile ramFile;
+
+    // Connect to file server:
+    User::LeaveIfError( rFs.Connect() );
+    CleanupClosePushL( rFs );
+
+    if ( !BaflUtils::FileExists( rFs, *iClipInfo->iFileName ) )
+        {
+        User::Leave( KErrNotFound );
+        }
+
+    User::LeaveIfError( ramFile.Open( rFs, *iClipInfo->iFileName, EFileShareAny ) );
+    CleanupClosePushL( ramFile );
+
+    TInt size;
+    User::LeaveIfError( ramFile. Size( size ) );
+    if ( size > KBavpMaxLinkFileSize )
+        {
+        User::Leave( KErrNotFound );
+        }
+
+    HBufC8* urlBuf = HBufC8::NewLC( size );
+    TPtr8 ptr = urlBuf->Des();
+
+    // Read file to urlBuf
+    User::LeaveIfError( ramFile.Read( ptr ) );
+
+    // Set the iClipInfo->iUrl
+    if ( iClipInfo->iUrl )
+        {
+        delete iClipInfo->iUrl;
+        iClipInfo->iUrl = NULL;
+        }
+    iClipInfo->iUrl = HBufC::NewL( urlBuf->Length() );
+
+    TPtr urlDes = iClipInfo->iUrl->Des();
+
+    // Read to the end of the line that should be a link
+    TInt lineChange = urlBuf->LocateF( EKeyLineFeed );
+    if ( lineChange == KErrNotFound )
+        {
+        // No line change was found --> last line had no line change
+        // Copy last line to (unicode) aLink
+        CnvUtfConverter::ConvertToUnicodeFromUtf8( urlDes, *urlBuf );
+        }
+    else
+        {
+        // Set the descriptor to the  end of the line
+        if ( (lineChange > 0) && (urlBuf->Des()[lineChange - 1] == EKeyEnter) )
+            {
+            lineChange--;
+            }
+
+        // Copy line to (unicode) url
+        CnvUtfConverter::ConvertToUnicodeFromUtf8( urlDes, urlBuf->Left( lineChange ) );
+        }
+
+    CleanupStack::PopAndDestroy( 3 ); // ramFile, urlBuf, rFs
+    }
+
+
+#if defined(BRDO_ASX_FF)
+// -----------------------------------------------------------------------------
+// CBavpController::ParseAsxFileL
+// Read the asx file and parse the the url, put into iClipInfo->iUrl
+// Only retrieve the first URL found
+// -----------------------------------------------------------------------------
+void CBavpController::ParseAsxFileL()
+    {
+    Log( EFalse, _L("CBavpController::ParseAsxFileL() ") );
+
+    TUint urls = 0;
+    TPtrC8 url;
+
+    if ( iClipInfo->iUrl )
+        {
+        delete iClipInfo->iUrl;
+        iClipInfo->iUrl = NULL;
+        }
+
+    CAsxParser* asxParser = CAsxParser::NewL(*iClipInfo->iFileName);
+
+    CleanupStack::PushL( asxParser );
+
+    if ( asxParser )
+        {
+        asxParser->GetUrlCount(urls);
+        if ( urls > 0 )
+            asxParser->GetUrl(1,url);
+        }
+
+    iClipInfo->iUrl = HBufC::NewL( url.Length() );
+    TPtr urlDes = iClipInfo->iUrl->Des();
+    CnvUtfConverter::ConvertToUnicodeFromUtf8( urlDes, url);
+
+    CleanupStack::PopAndDestroy();  // asxparser
+    }
+#endif // BRDO_ASX_FF
+
+
+// CBavpController::GetClipRect
+// Retrieve the rect position. Ex. not intersect with title pane and status pane
+// -----------------------------------------------------------------------------
+TRect CBavpController::GetClipRect( TRect aRect )
+    {
+    TRect clipRect ( aRect );
+    Log( EFalse, _L("GetClipRect") );
+
+    AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, iNormalScreenRect );
+
+  // Calculate not to cover the bottom or the top of the rect.
+  if ( clipRect.iTl.iX < iNormalScreenRect.iTl.iX )
+    {
+    clipRect.iTl.iX = iNormalScreenRect.iTl.iX;
+    }
+
+  if ( clipRect.iTl.iY < iNormalScreenRect.iTl.iY )
+    {
+    clipRect.iTl.iY = iNormalScreenRect.iTl.iY;
+    }
+
+  if ( clipRect.iBr.iY > iNormalScreenRect.iBr.iY )
+    {
+    clipRect.iBr.iY = iNormalScreenRect.iBr.iY;
+    }
+
+  if ( clipRect.iBr.iX > iNormalScreenRect.iBr.iX )
+    {
+    clipRect.iBr.iX = iNormalScreenRect.iBr.iX - KRectPadding;
+    }
+
+    return clipRect;
+    }
+
+// -----------------------------------------------------------------------------
+// CBavpController::CreateVolumeListDlg
+// Create the volume list query dialog
+// -----------------------------------------------------------------------------
+void CBavpController::CreateVolumeListDlgL()
+{
+    CEikTextListBox* list = new(ELeave) CAknSinglePopupMenuStyleListBox;
+    CleanupStack::PushL( list );
+
+    // Create popup list and PUSH it.
+    CAknPopupList* popupList = CAknPopupList::NewL( list,
+                                                    R_AVKON_SOFTKEYS_OK_CANCEL,
+                                                    AknPopupLayouts::EMenuWindow);
+    CleanupStack::PushL( popupList );
+
+    // Initialize listbox.
+    list->ConstructL( popupList, CEikListBox::ELeftDownInViewRect );
+    list->CreateScrollBarFrameL( ETrue );
+    list->ScrollBarFrame()->SetScrollBarVisibilityL( CEikScrollBarFrame::EOff,
+                                                     CEikScrollBarFrame::EAuto );
+
+    // Make list items and PUSH it
+    CDesCArrayFlat* items =
+            CCoeEnv::Static()->ReadDesCArrayResourceL( R_AKNTAPOPLIST_MENU_VOLUME_ITEMS );
+
+    // Set list items.
+    CTextListBoxModel* model = list->Model();
+    model->SetItemTextArray( items );
+    model->SetOwnershipType( ELbmOwnsItemArray );
+
+    // Using the current volume set to determine the index of the volume value
+    // to highlight in the list
+    TInt volumeIndex( 0 );
+    if ( iCurrentVolume == KCRVolume0 )
+        {
+        volumeIndex = 0;
+        }
+    else if ( iCurrentVolume == KCRVolume2 )
+        {
+        volumeIndex = 1;
+        }
+    else if ( iCurrentVolume == KCRVolume5 )
+        {
+        volumeIndex = 2;
+        }
+    else if ( iCurrentVolume == KCRVolume8 )
+        {
+        volumeIndex = 3;
+        }
+    else if ( iCurrentVolume == KCRVolume10 )
+        {
+        volumeIndex = 4;
+        }
+
+    // Highlight the current item in the list box
+    list->SetCurrentItemIndexAndDraw( volumeIndex );
+
+    HBufC* title = CCoeEnv::Static()->AllocReadResourceLC( R_TEXT_VIDEO_PLUGIN_MEDIA_VOLUME);
+    popupList->SetTitleL( *title );
+    CleanupStack::PopAndDestroy();  // title
+
+    // Show popup list and then show return value.
+    TInt popupOk = popupList->ExecuteLD();
+    CleanupStack::Pop();    // popuplist
+
+    // Handle the returned value from the volume list dialog
+    if ( popupOk )
+        {
+        // Check if there is change for the volume select
+        if ( volumeIndex != list->CurrentItemIndex() )
+            {
+            // Set the current index to volume index
+            volumeIndex = list->CurrentItemIndex();
+
+            // To match the list box data to the values defined in
+            // the Central repository: (mute)0,2,5,8,10(maximum)
+            if ( volumeIndex == 0 )
+                {
+                iCurrentVolume = KCRVolume0;
+                }
+            else if ( volumeIndex == 1 )
+                {
+                iCurrentVolume = KCRVolume2;
+                }
+            else if ( volumeIndex == 2 )
+                {
+                iCurrentVolume = KCRVolume5;
+                }
+            else if ( volumeIndex == 3 )
+                {
+                iCurrentVolume = KCRVolume8;
+                }
+            else if ( volumeIndex == 4 )
+                {
+                iCurrentVolume = KCRVolume10;
+                }
+
+            Log( EFalse, _L("Return Volume from Player="), iCurrentVolume );
+
+            // Tell the volume handler about our new volume the user selected
+            iBavpVolumeHandler->HandleNotifyInt( KBrowserMediaVolumeControl,
+                                                 iCurrentVolume );
+            }
+        }
+
+    CleanupStack::PopAndDestroy();  // list
+}
+
+// -----------------------------------------------------------------------------
+// CBavpController::IsVideoOrAudioCall
+// Check if there is an incoming call
+// -----------------------------------------------------------------------------
+TBool CBavpController::IsVideoOrAudioCall()
+    {
+    Log( EFalse, _L("CBavpController::IsVideoOrAudioCall() entered") );
+
+    // Pause if there is video call
+    TInt callType;
+
+    RProperty::Get( KPSUidCtsyCallInformation,
+                    KCTsyCallType,
+                    callType ); // Ignore errors
+
+    return ( callType == EPSCTsyCallTypeH324Multimedia ||
+             callType == EPSCTsyCallTypeCSVoice );
+    }
+
+// -----------------------------------------------------------------------------
+// CBavpController::BaseConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+void CBavpController::BaseConstructL( TBavpMediaType aMediaType,
+                                      const TDesC& aFileName )
+    {
+    Log( EFalse, _L("CBavpController::BaseConstructL enter") );
+
+    // Create Clipinfo
+    iClipInfo = new (ELeave) CBavpClipInfo();
+    iClipInfo->iMediaType = aMediaType;
+    iClipInfo->iFileName = aFileName.AllocL();
+    iClipInfo->iUrl = aFileName.AllocL();
+
+    // Watch for incoming calls
+    User::LeaveIfError( iIncomingCalls.Attach( KPSUidCtsyCallInformation,
+                        KCTsyCallState ) );
+    iIncomingCalls.Subscribe( iStatus );
+
+    // Set the AO active. so we will watch for incoming calls, see RunL()
+    SetActive();
+
+    // Create Volume Handler to get the initial volume from settings CR, and
+    // watch the CR for volume changes (browser or system)
+    iBavpVolumeHandler = CBavpVolumeHandler::NewL( this );
+
+    // Create the timer for jumping (skipping) to new position
+    iPositionUpdater = CPeriodic::NewL( CActive::EPriorityStandard );
+
+  //Get normal display screen rect - not including title pane and toolbar pane
+  AknLayoutUtils::LayoutMetricsRect( AknLayoutUtils::EMainPane, iNormalScreenRect );
+    // If the phone has side volume keys, create an observer for the hardware
+    // volume key events
+    if ( HAS_HW_VOLUME_KEYS )
+        {
+        TRAP_IGNORE(iHwKeyEvents = CBavpHwKeyEvents::NewL( *this ) );
+        }
+
+    // Add this BavpController instance to the array
+    iBavpControllerArray.Append( this );
+
+    Log( EFalse, _L("CBavpController::BaseConstructL exited") );
+    }
+
+// -----------------------------------------------------------------------------
+// CBavpControllerVideo::RunL
+// If incoming call arrives, handle the audio or video player content.
+// If incoming call ends, resume the audio or video player
+// -----------------------------------------------------------------------------
+void CBavpController::RunL()
+    {
+    Log( EFalse, _L("CBavpController::RunL() entered") );
+
+    // Do we have an incoming audio or video call
+    if ( IsVideoOrAudioCall() )
+        {
+        // If we are playing content, pause if seekable or stop if streaming
+        if ( iCurrentState == EBavpPlaying )
+            {
+            // Set precall state, so we will resume playing the content,
+            // after the call is done
+            iPreCallState = EBavpPlaying;
+
+            if ( iClipInfo->iSeekable )
+                {
+                // Seekable content, pause, if there is an incoming call
+                PauseL();
+                }
+            else
+                {
+                HandleInComingCallL();
+                // Streaming content, stop, if there is an incoming call
+                Stop();
+                }
+            }
+        // If we are seeking content, pause it (these states only for seekable)
+        else if ( iCurrentState == EBavpFastForwarding ||
+                  iCurrentState == EBavpRewinding )
+            {
+            // Set precall state, so we will not resume playing the content,
+            // after the call is done
+            iPreCallState = EBavpPaused;
+
+            // Stop the position updater
+            if ( iPositionUpdater->IsActive() )
+                {
+                iPositionUpdater->Cancel();
+                }
+            // Seekable content, pause, if there is an incoming call
+            PauseL();
+            }
+        }
+    else
+        {
+        // If the prev status was playing and has been paused by a phone call
+        // or a video call. Try to get the player to the previous state and
+        // invoke play function.
+        if ( iPreCallState == EBavpPlaying )
+            {
+            iPreCallState = EBavpNone;
+            PlayL();
+            }
+        }
+
+    // Listen for the incoming call property changes
+    iIncomingCalls.Subscribe( iStatus );
+
+    SetActive();
+    }
+
+// -----------------------------------------------------------------------------
+// CBavpController::UpdateVolume
+// From MBavpVolumeObserver
+// Provides CBavpController with the media volume from the VolumeHandler
+// -----------------------------------------------------------------------------
+void CBavpController::UpdateVolume( TInt aVolume )
+    {
+    iCurrentVolume = aVolume;
+
+    // Notify Player of volume change
+    SetPlayerVolume( iCurrentVolume );
+    }
+
+// -----------------------------------------------------------------------------
+// CBavpController::BavpHwKeyVolumeChange
+// Handles the change in the Volume that is needed as per the Hardware Volume
+// key events. Remember, all volume levels in CBavpController are CR based,
+// values 0(mute) - 10(max). Use KCRVolumeX values.
+// -----------------------------------------------------------------------------
+void CBavpController::BavpHwKeyVolumeChange( TInt aVolumeChange )
+    {
+    TInt newVolume = iCurrentVolume;
+    newVolume += aVolumeChange;
+
+    Log( EFalse, _L("CBavpController::BavpHwKeyVolumeChange newVolume="), newVolume );
+
+    // Ensure the volume is within range
+    if ( newVolume < KCRVolume0 )
+        {
+        newVolume = KCRVolume0;
+        }
+    else if ( newVolume > KCRVolumeMax )
+        {
+        newVolume = KCRVolumeMax;
+        }
+
+    // Piggyback on this call to set the new volume from
+    iBavpVolumeHandler->HandleNotifyInt( KBrowserMediaVolumeControl, newVolume );
+    }
+
+// -----------------------------------------------------------------------------
+// CBavpController::IsAnotherControllerPlaying
+// Returns ETrue, on the first controller it finds in playing state
+// -----------------------------------------------------------------------------
+TBool CBavpController::IsAnotherControllerPlaying()
+    {
+    if ( iBavpControllerArray.Count() > 1 )
+        {
+        for ( TInt i( 0 ); i < iBavpControllerArray.Count(); i++ )
+            {
+            CBavpController* bavpController = iBavpControllerArray[ i ];
+            if ( ( this != bavpController ) &&
+                 ( bavpController->iCurrentState == EBavpPlaying ) )
+                {
+                return ETrue;
+                }
+            }
+        }
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CBavpController::PauseOtherControllersPlaying
+// This will attempt to pause all of the other controllers (expect this one), if
+// the media can't be paused (ie live stream), it will be stopped.
+// -----------------------------------------------------------------------------
+void CBavpController::PauseOtherControllersPlaying()
+    {
+    if ( iBavpControllerArray.Count() > 1 )
+        {
+        for ( TInt i( 0 ); i < iBavpControllerArray.Count(); i++ )
+            {
+            CBavpController* bavpController = iBavpControllerArray[ i ];
+            if ( this != bavpController )
+                {
+                TRAP_IGNORE( bavpController->PauseL() );
+                iBavpView->UpdateView();
+                }
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CBavpControllerVideo::HandleMultiInstanceError
+// Handle error codes.
+// 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 CBavpController::HandleMultiInstanceError()
+    {
+    // Handle multiple media object case
+    if ( iBavpControllerArray.Count() > 1 && IsAnotherControllerPlaying() )
+        {
+        if ( iLastCommand == EBavpCmdUnknown )
+            {
+            // Another controller is playing, and this controller was
+            // initializing, so our error is because we can only play one
+            // media object at a time. Stop this media and let
+            // the first one initialized continue to play.
+            //TRAP_IGNORE( PauseL() );
+            Stop();
+            iBavpView->UpdateView();
+            }
+        else if ( iLastCommand == EBavpCmdPlay )
+            {
+            // Another controller is playing, and the user wants to play
+            // another media object. Pause (or stop) all of the others and
+            // play this one.
+            PauseOtherControllersPlaying();
+            TRAP_IGNORE( PlayL() );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CBavpController::SetOriginalFileName
+// Sets the file name. Used for scripting functionality
+// -----------------------------------------------------------------------------
+void CBavpController::SetOriginalFileName( const TDesC* originalFile )
+{
+    if ( originalFile )
+    {
+        iOriginalFileName = originalFile->Alloc();
+    }
+}
+
+// -----------------------------------------------------------------------------
+// CBavpController::SetMimeType
+// Sets the mime type. Used for scripting functionality
+// -----------------------------------------------------------------------------
+void CBavpController::SetMimeType( const TDesC8* mimetype )
+{
+    if ( mimetype )
+    {
+        iMimeType = mimetype->Alloc();
+    }
+}
+
+// -----------------------------------------------------------------------------
+// CBavpController::BavpHwKeyCommand
+// Handles transport commands (play, pause, ...) from dedicated hardware keys.
+// -----------------------------------------------------------------------------
+/*
+void CBavpController::BavpHwKeyCommand( TBavpCommandIds aCommand )
+    {
+    // Do some basic checks for the hardware keys
+    if ( aCommand == EBavpCmdPlay && iCurrentState == EBavpPlaying )
+        {
+        // We recieved a play command while playing, therefore make it pause
+        aCommand = EBavpCmdPause;
+        }
+
+    HandleCommandL( aCommand );
+    }
+*/
+//  End of File