diff -r 000000000000 -r 7f85d04be362 upnpframework/upnpaiwengine/src/upnpaiwengine.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/upnpframework/upnpaiwengine/src/upnpaiwengine.cpp Thu Dec 17 08:52:00 2009 +0200 @@ -0,0 +1,1709 @@ +/* +* Copyright (c) 2005-2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "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: Implementation of the class CUPnPAiwEngine. + * +*/ + + +// INCLUDE FILES +// System +#include +#include +#include +#include +#include + +// Upnp stack +#include + +// avcontroller api +#include "upnpavcontroller.h" +#include "upnpavcontrollerfactory.h" +#include "upnpavrenderingsession.h" +#include "upnpavsessionbase.h" +#include "upnpavdevice.h" + +// avcontroller / avcontroller helper api +#include "upnpitemresolver.h" +#include "upnpitemresolverfactory.h" +#include "upnpitemutility.h" +#include "upnpresourceselector.h" + +// upnpframework internal api's +#include "upnpfiletransferengine.h" // Upnp Fw / UpnpFileTransferEngine +#include "upnpcommonutils.h" // Upnp Fw / UpnpUtilities + +// aiw engine internal +#include // Upnp Fw / UpnpAiwEngine +#include "upnpaiwengine.h" // Upnp Fw / UpnpAiwEngine +#include "upnpaiwtimer.h" // Upnp Fw / UpnpAiwEngine + +// logging +_LIT( KComponentLogfile, "upnpaiwengine.log" ); +#include "upnplog.h" + +const TInt KSlash = 92; +const TInt KDot = 46; + +// CONSTANTS +_LIT( KResFileName, "\\resource\\upnpaiwengineresources.rsc" ); +const TInt KAiwTimerIntervalInSeconds = 1; + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::NewL +// NewL. +// -------------------------------------------------------------------------- +// +EXPORT_C CUPnPAiwEngine* CUPnPAiwEngine::NewL() + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::NewL" ); + + CUPnPAiwEngine* self = NULL; + + // If this is the first time we are getting the instance of this + // singleton class, create the instance and store it into the + // Thread Local Storage + if( !Dll::Tls() ) + { + self = new (ELeave) CUPnPAiwEngine; + + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + + TInt err = Dll::SetTls( static_cast( self ) ); + if( err != KErrNone ) + { + delete self; + self = NULL; + } + else + { + // Initialise the user counter to zero + self->InitialiseUserCounter(); + } + } + else + { + self = static_cast( Dll::Tls() ); + } + + // Increase number of users by one + self->IncreaseUserCounter(); + return self; + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::ReleaseInstance +// Releases the instance. +// -------------------------------------------------------------------------- +// +EXPORT_C void CUPnPAiwEngine::ReleaseInstance() + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::ReleaseInstance" ); + + CUPnPAiwEngine* instance = NULL; + + // Get the instance from the TLS if there is an instance + if( Dll::Tls() ) + { + instance = static_cast( Dll::Tls() ); + } + + // If there still were an instance in the TLS + if( instance ) + { + + // Decrease the number of instance + instance->DecreaseUserCounter(); + + // If the instance count is now 0, empty the TLS + if( instance->UserCounter() <= 0 ) + { + // Empty the TLS + TInt err = Dll::SetTls( NULL ); + if( err ) + { + // ignore + } + + // Delete the instance + delete instance; + instance = NULL; + } + } + } + +// -------------------------------------------------------------------------- +// Constructor +// -------------------------------------------------------------------------- +// +CUPnPAiwEngine::CUPnPAiwEngine() + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::CUPnPAiwEngine" ); + + iRenderingSessionInUse = EFalse; + iVideoPlay = EFalse; + iFileName = NULL; + iVideoPlayCancel = EFalse; + iVideoPlayWait = EFalse; + } + +// -------------------------------------------------------------------------- +// Destructor +// -------------------------------------------------------------------------- +// +CUPnPAiwEngine::~CUPnPAiwEngine() + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::~CUPnPAiwEngine" ); + // Delete resolvers + // Delete for resolvers is done using temporary variables so that we can + // first nullify the members and then delete the actual objects. + // This is because local resolver deletion uses active scheduler loops + // and therefore other asynchronous events may orrur. So we may end + // up here in Cleanup again, during the resolver is being deleted. + // if deletion is done the conventional way, the objects get deleted + // twice, which is not what we want. :-) + MUPnPItemResolver* tempResolver = iResolver; + iResolver = NULL; + delete tempResolver; + StopTimer(); + + // If wait note is shown, finish it + if (iWaitNoteDialog) + { + TRAP_IGNORE( iWaitNoteDialog->ProcessFinishedL() ); + } + + if (iRenderingSession && iAVController) + { + TRAP_IGNORE( iAVController->StopRenderingSession( + *iRenderingSession ) ); + iRenderingSession = NULL; + } + + delete iCommonUI; + + // Delete the UPnP AV Controller + delete iAVController; + delete iFileName; + + // Un-load resource file + if (iResFileOffset) + { + CEikonEnv::Static()->DeleteResourceFile(iResFileOffset); + iResFileOffset = 0; + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::ConstructL +// Second phase constructor +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::ConstructL() + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::ConstructL" ); + + iCoeEnv = CEikonEnv::Static(); + RFs& fileSession = iCoeEnv->FsSession(); + + // Load resource file + TFileName rscFileName(KResFileName); + TFileName dllName; + Dll::FileName(dllName); + TBuf<2> drive = dllName.Left(2); // Drive letter followed by ':' + rscFileName.Insert( 0, drive); + + // Get the exact filename of the resource file + BaflUtils::NearestLanguageFile(fileSession, rscFileName); + + // Check if the resource file exists or not + if ( !BaflUtils::FileExists(fileSession, rscFileName) ) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine, resource file does not \ +exist!" ); + User::Leave(KErrNotFound); + } + + if (iCoeEnv) + { + // Read the resource file offset + iResFileOffset = iCoeEnv->AddResourceFileL(rscFileName); + } + + // Set initial state of the connection to the UPnPAVController + iCommonUI = CUPnPCommonUI::NewL(); + iAVController = NULL; + iRenderingSession = NULL; + iEngineState = EUPnPEngineNotConnected; + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::SetEngineObserver +// Sets the observer instance. +// -------------------------------------------------------------------------- +// +EXPORT_C void CUPnPAiwEngine::SetEngineObserver( + MUPnPAiwEngineObserver* aObserver ) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::SetEngineObserver" ); + + if( aObserver ) + { + iObserver = aObserver; + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::RemoveEngineObserver +// Sets the observer instance. +// -------------------------------------------------------------------------- +// +EXPORT_C void CUPnPAiwEngine::RemoveEngineObserver() + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::RemoveEngineObserver" ); + + iObserver = NULL; + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::EngineState +// Gets the state of the UPnP AIW Engine. +// -------------------------------------------------------------------------- +// +EXPORT_C TUPnPEngineState CUPnPAiwEngine::EngineState() + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::EngineState" ); + + return iEngineState; + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::OpenExternalMediaL +// Opens the External media UI. +// -------------------------------------------------------------------------- +// +EXPORT_C void CUPnPAiwEngine::OpenExternalMediaL() + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::OpenExternalMediaL" ); + + TInt status = KErrNone; + + if( !iAVController && + iEngineState == EUPnPEngineNotConnected ) + { + TRAP( status, + iAVController = + UPnPAVControllerFactory::NewUPnPAVControllerL() ); + + if( status == KErrNone && + iAVController ) + { + // Update engine state + iEngineState = EUPnPEngineBrowsingHomeNetwork; + TInt leaveCode = KErrNone; + + TRAP( leaveCode, + status = iCommonUI->ExecuteDeviceDialogL( *iAVController ) ); + + // Handle status and leave codes + if( leaveCode != KErrNone && + status == KErrNone ) + { + status = leaveCode; + } + + // Clean up and return the engine state + delete iAVController; + iAVController = NULL; + iEngineState = EUPnPEngineNotConnected; + } + else // If the instantiation of UpnpAvController fails + + { + TRAP_IGNORE( ShowConnectionErrorL() ); + status = KErrCouldNotConnect; + } + } + else // If the UpnpAvController is already instantiated + + { + status = KErrInUse; + } + + if( status != KErrNone ) + { + User::Leave( status ); + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::EnableExternalL +// Enables the showing of local media files on a remote renderer device. +// -------------------------------------------------------------------------- +// +EXPORT_C void CUPnPAiwEngine::EnableExternalL() + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::EnableExternalL" ); + + TInt status = KErrNone; + + if( !iAVController && + iEngineState == EUPnPEngineNotConnected ) + { + TRAP( status, + iAVController = + UPnPAVControllerFactory::NewUPnPAVControllerL() ); + + if( status == KErrNone && + iAVController ) + { + iAVController->SetDeviceObserver( *this ); + TRAP( status, StartRenderingSessionL( + EUPnPAiwEngineTargetDeviceWithImageSupport ) ); + + // If the rendering session was created successfully + if( status == KErrNone && + iRenderingSession ) + { + // Start local file sharing + TRAP( status, + StartLocalFileSharingL( iRenderingSession ) ); + { + // If the file sharing failed to start, undo the enable + // external by calling disable external. + if( status != KErrNone ) + { + DisableExternal(); + } + } + } + else + { + delete iAVController; + iAVController = NULL; + iEngineState = EUPnPEngineNotConnected; + } + } + else // If the instantiation of UpnpAvController fails + + { + TRAP_IGNORE( ShowConnectionErrorL() ); + status = KErrCouldNotConnect; + } + } + else + { + status = KErrInUse; + } + + if( status != KErrNone ) + { + User::Leave( status ); + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::DisableExternal +// Disables the showing of local media files on a remote renderer device. +// -------------------------------------------------------------------------- +// +EXPORT_C void CUPnPAiwEngine::DisableExternal() + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::DisableExternal" ); + + if( iAVController ) + { + if( iRenderingSession ) + { + // If STOP action is required, use the timer to delay the + // destruction (give some time for AvController to send the STOP + // action message) + if( iEngineState == EUPnPEngineActive ) + { + TRAP_IGNORE( iRenderingSession->StopL() ); + StartTimer(); + } + else + { + // Stop local file sharing + TRAP_IGNORE( iRenderingSession->ReleaseLocalMSServicesL() ); + + // Stop the rendering session + TRAP_IGNORE( iAVController->StopRenderingSession( + *iRenderingSession ) ); + iRenderingSession = NULL; + } + } + + // Delete the UPnP AV Controller + delete iAVController; + iAVController = NULL; + } + + // Update engine state + iRenderingSessionInUse = EFalse; + iEngineState = EUPnPEngineNotConnected; + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::PlayL +// Plays (sends for rendering) local media file using the selected +// UPnP Media renderer. +// -------------------------------------------------------------------------- +// +EXPORT_C void CUPnPAiwEngine::PlayL( const TDesC& aFileName ) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::PlayL" ); + + TInt status = KErrNone; + + if( aFileName != KNullDesC ) + { + + if( iAVController && + iRenderingSession && + ( iEngineState == EUPnPEngineConnected || + iEngineState == EUPnPEngineActive ) ) + { + + // Check the file type + TUPnPItemType fileType = ETypeOther; + TRAPD( mimeError, + fileType = UPnPCommonUtils::ResolveFileTypeL( + aFileName ) ); + if( mimeError == KErrNone ) + { + if( fileType == ETypeAudio ) + { + status = KErrNotSupported; + if( iObserver ) + { + iObserver->PlayCompleteL( status ); + } + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine, \ +audio files not supported!" ); + } + else if ( fileType == ETypeVideo ) + { + if( iRenderingSessionInUse ) + { + //if the previous operation not finished + delete iFileName; iFileName = NULL; + iFileName = aFileName.AllocL(); + iVideoPlayWait = ETrue; + } + else + { + TRAP( status, StartVideoPlayL( aFileName ) ); + } + } + else if ( fileType == ETypeImage ) + { + if( !iVideoPlay ) //if no video is being played + + { + if( iRenderingSessionInUse ) + { + //if the previous operation not finished + iVideoPlayWait = EFalse; + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine, \ +iRenderingSessionInUse: ETrue" ); + delete iFileName; + iFileName = NULL; + iFileName = aFileName.AllocL(); + } + else + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine, \ +iRenderingSessionInUse: EFalse" ); + TRAP( status , CreateUpnpItemAndSetUriL( aFileName ) ); + if( KErrNone == status ) + { + iRenderingSessionInUse = ETrue; + } + else + { + // Failed, notify MG, the image playing is + // complete + if( iObserver ) + { + iObserver->PlayCompleteL( status ); + } + } + } + } + else + { + //notify MG, the music playing is complete + if( iObserver ) + { + iObserver->PlayCompleteL( status ); + } + } + + } + else // Unsupported file + + { + status = KErrNotSupported; + } + } + else // Failed to resolve MIME type + + { + status = KErrArgument; + } + } + else // Rendering session not available (Enable External not done) + + { + status = KErrNotReady; + } + } + else + { + status = KErrArgument; + } + + if( status != KErrNone ) + { + User::Leave( status ); + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::CopyToExternalL +// Copies local files to a remote media server. +// -------------------------------------------------------------------------- +// +EXPORT_C void CUPnPAiwEngine::CopyToExternalL( + RPointerArray& aFileNames ) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::CopyToExternalL" ); + + // Check parameters + if( aFileNames.Count() <= 0 ) + { + User::Leave( KErrArgument ); + } + + // Check engine state + if( iAVController ) + { + User::Leave( KErrInUse ); + } + + // Create UPnPAVController + TRAPD( avControllerError, + iAVController = UPnPAVControllerFactory::NewUPnPAVControllerL() ); + if( avControllerError != KErrNone ) + { + TRAP_IGNORE( ShowConnectionErrorL() ); + User::Leave( KErrCouldNotConnect ); + } + + // Update engine state + iEngineState = EUPnPEngineConnected; + + // Do the transfer + TRAPD( transferError, + TransferToExternalL( EAiwEngineCopy, aFileNames, KNullDesC ) ); + + // Clean up + delete iAVController; + iAVController = NULL; + + // Update engine state + iEngineState = EUPnPEngineNotConnected; + + if( transferError != KErrNone ) + { + User::Leave( transferError ); + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::CopyToExternalL +// Copies local files to a remote media server. +// -------------------------------------------------------------------------- +// +EXPORT_C void CUPnPAiwEngine::CopyPlaylistToExternalL( + const TDesC& aPlaylistName, + RPointerArray& aFileNames ) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::CopyPlaylistToExternalL" ); + + // Check parameters + if( aFileNames.Count() <= 0 || + aPlaylistName == KNullDesC ) + { + User::Leave( KErrArgument ); + } + + // Check engine state + if( iAVController ) + { + User::Leave( KErrInUse ); + } + + // Create UPnPAVController + TRAPD( avControllerError, + iAVController = UPnPAVControllerFactory::NewUPnPAVControllerL() ); + if( avControllerError != KErrNone ) + { + TRAP_IGNORE( ShowConnectionErrorL() ); + User::Leave( KErrCouldNotConnect ); + } + + // Update engine state + iEngineState = EUPnPEngineConnected; + + // Do the transfer + TRAPD( transferError, + TransferToExternalL( EAiwEngineCopyPlaylist, + aFileNames, + aPlaylistName ) ); + + // Clean up + delete iAVController; + iAVController = NULL; + + // Update engine state + iEngineState = EUPnPEngineNotConnected; + + if( transferError != KErrNone ) + { + User::Leave( transferError ); + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::MoveToExternalL +// Moves local files to a remote media server. +// -------------------------------------------------------------------------- +// +EXPORT_C void CUPnPAiwEngine::MoveToExternalL( + RPointerArray& aFileNames ) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::MoveToExternalL" ); + + // Check parameters + if( aFileNames.Count() <= 0 ) + { + User::Leave( KErrArgument ); + } + + // Check engine state + if( iAVController ) + { + User::Leave( KErrInUse ); + } + + // Create UPnPAVController + TRAPD( avControllerError, + iAVController = UPnPAVControllerFactory::NewUPnPAVControllerL() ); + if( avControllerError != KErrNone ) + { + TRAP_IGNORE( ShowConnectionErrorL() ); + User::Leave( KErrCouldNotConnect ); + } + + // Update engine state + iEngineState = EUPnPEngineConnected; + + // Do the transfer + TRAPD( transferError, + TransferToExternalL( EAiwEngineMove, aFileNames, KNullDesC ) ); + + // Clean up + delete iAVController; + iAVController = NULL; + + // Update engine state + iEngineState = EUPnPEngineNotConnected; + + if( transferError != KErrNone ) + { + User::Leave( transferError ); + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::TransferToExternalL +// Transfers (copies/moves) local files/playlists to a remote media server. +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::TransferToExternalL(TUPnPAiwEngineTransferMode aMode, + RPointerArray& aFilePaths, const TDesC& aPlaylistName) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::TransferToExternalL" ); + + // Parameters were already checked + + // Select the target server device + // Title should be according to ui spec. + TUPnPDialogTitle title = EUPnPCopyToTitle; + if (aMode == EAiwEngineMove) + { + title = EUPnPMoveToTitle; + } + CUpnpAVDevice* targetDevice = SelectDeviceL( + EUPnPSearchServerDevicesWithCopyCapability, title); + + CleanupStack::PushL(targetDevice); + + // Create a browsing session + TInt status = KErrNone; + MUPnPAVBrowsingSession* browsingSession= NULL; + TRAP( status, browsingSession = + &iAVController->StartBrowsingSessionL( *targetDevice ) ); + + if (status == KErrNone && browsingSession) + { + // Create a file transfer engine instance + CUpnpFileTransferEngine* ftEngine= NULL; + TRAP( status, + ftEngine = CUpnpFileTransferEngine::NewL( browsingSession ) ); + if ( status == KErrNone && ftEngine ) + { + CleanupStack::PushL( ftEngine ); + + // Update engine state + iEngineState = EUPnPEngineActive; + + // Number of files in the array. + TInt count = aFilePaths.Count(); + + // Do the copy/move + if ( aMode == EAiwEngineMove ) + { + TRAP( status, ftEngine->MoveLocalFilesToRemoteServerL( + &aFilePaths ) ); + } + else if ( aMode == EAiwEngineCopyPlaylist) + { + TRAP( status, ftEngine->CopyLocalPlaylistToRemoteServerL( + aPlaylistName, + &aFilePaths ) ); + } + else + { + TRAP( status, ftEngine->CopyLocalFilesToRemoteServerL( + &aFilePaths ) ); + } + + // Clean up + // aFilePaths is not updates until ftEngine is deleted! + CleanupStack::PopAndDestroy( ftEngine ); + ftEngine = NULL; + + // Update engine state + if ( status == KErrNone ) + { + iEngineState = EUPnPEngineConnected; + + // Shows proper info note. + // + // Calculate number of transferred files based on original + // file count and items remaining in aFilePaths + // (those were NOT transferred) + ShowTransferInfoNoteL( + aMode, + count - aFilePaths.Count(), + *targetDevice ); + } + else if (KErrSessionClosed == status || KErrCouldNotConnect == status + || KErrDisconnected == status ) + { + iEngineState = EUPnPEngineConnectionLost; + if ( aMode != EAiwEngineMove ) + { + ShowConnectionLostCopyErrorL(); + } + else + { + ShowConnectionErrorL(); + } + } + else if ( KErrNotFound == status ) + { + ShowTransferInfoNoteL ( + aMode, + 0, + *targetDevice ); + } + else + { + iEngineState = EUPnPEngineConnected; + } + } + + // Stop browsing session + iAVController->StopBrowsingSession( *browsingSession ); + } + + // Clean up + CleanupStack::PopAndDestroy( targetDevice ); + targetDevice = NULL; + + // Get the titles (of the files that failed to be transfered) from + // the item array and store them in the file name array. + TChar slash( KSlash ); + TChar dot( KDot ); + TInt fileCount = aFilePaths.Count(); + RPointerArray fileTitles; + for ( TInt index = 0; index < fileCount; index++ ) + { + TInt offset1 = aFilePaths[index]->LocateReverse( slash ); + TInt offset2 = aFilePaths[index]->LocateReverse( dot ); + + HBufC16* fileTitle= NULL; + + if ( KErrNotFound != offset1 && KErrNotFound != offset2 && + offset2 > ( offset1 + 1 ) ) + { + + fileTitle = aFilePaths[index]-> + Mid( ( offset1 + 1 ), ( offset2 - offset1 - 1 ) ).Alloc(); + + } + if (fileTitle) + { + fileTitles.Append(fileTitle); + } + } + aFilePaths.ResetAndDestroy(); + for (TInt index = 0; index < fileTitles.Count(); index++) + { + aFilePaths.Append(fileTitles[index]); + } + + fileTitles.Reset(); + fileTitles.Close(); + + if (status != KErrNone) + { + User::Leave(status); + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::StartRenderingSessionL +// Starts a rendering session with UpnpAvController. Queries the target +// rendering device. +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::StartRenderingSessionL(TUPnPAiwEngineDeviceType aType) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::StartRenderingSessionL" ); + + TInt status = KErrNone; + + if (iAVController) + { + if ( !iRenderingSession) + { + CUpnpAVDevice* tempDevice = CUpnpAVDevice::NewL(); + CleanupStack::PushL(tempDevice); + + // Launch the device selection dialog + + if (aType == EUPnPAiwEngineTargetDeviceWithAudioSupport) + { + status = iCommonUI->SelectDeviceL( *iAVController, + *tempDevice, + EUPnPSearchRenderingDevicesWithAudioCapability, + EUPnPSelectDeviceTitle); + } + else + if (aType + == EUPnPAiwEngineTargetDeviceWithImageAndVideoSupport) + { + status = iCommonUI->SelectDeviceL( *iAVController, + *tempDevice, + EUPnPSearchRenderingDevicesWithVideoCapability, + EUPnPSelectDeviceTitle); + } + else + if (aType == EUPnPAiwEngineTargetDeviceWithImageSupport) + { + status + = iCommonUI->SelectDeviceL( + *iAVController, + *tempDevice, + EUPnPSearchRenderingDevicesWithImageCapability, + EUPnPSelectDeviceTitle); + } + else + { + status = KErrNotSupported; + } + + if (status == KErrNone) + { + // Create a rendering session and register to observe the + // callbacks + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine, \ +creating rendering session." ); + iRenderingSession + = &(iAVController->StartRenderingSessionL( *tempDevice) ); + iRenderingSession->SetObserver( *this); + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine, \ +rendering session created." ); + + // Update the engine state + iEngineState = EUPnPEngineConnected; + } + + // Clean up + CleanupStack::PopAndDestroy(tempDevice); + tempDevice = NULL; + } + else + { + status = KErrInUse; + } + } + else + { + status = KErrNotReady; + } + + if (status != KErrNone) + { + User::Leave(status); + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::InteractOperationComplete +// UPnP AV Controller calls this method to indicate that the requested +// interaction operation (play, stop, etc.) is complete. +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::InteractOperationComplete(TInt aError, + TUPnPAVInteractOperation aOperation) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::InteractOperationComplete" ); + + if (iObserver && !iVideoPlayCancel) + { + // If the play operation is complete (stop) or the play fails, do + // the call back + if (aOperation == EUPnPAVPlay || aOperation == EUPnPAVPlayUser + || aOperation == EUPnPAVStop || aOperation == EUPnPAVStopUser) + { + iEngineState = EUPnPEngineConnected; + TRAP_IGNORE( iObserver->PlayCompleteL( aError ) ); + } + } + if (aOperation == EUPnPAVPlay || aOperation == EUPnPAVStop) + { + iRenderingSessionInUse = EFalse; + if (iFileName) // If there is a pending item + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine, pending item" ); + TRAP_IGNORE( InitPlayL() ); + delete iFileName; + iFileName = NULL; + iVideoPlayCancel = EFalse; // No need to send StopL + } + else + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine, no pending item" ); + + if (iVideoPlayCancel) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine, stop previous \ +video item," ); + iRenderingSessionInUse = ETrue; + TRAP_IGNORE( iRenderingSession->StopL() ); + iVideoPlayCancel = EFalse; //StopL sent + } + } + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::SetURIResult +// UPnP AV Controller calls this method to indicate that ... +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::SetURIResult(TInt aError) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::SetURIResult" ); + + iRenderingSessionInUse = EFalse; + if (aError != KErrNone && iObserver && !iVideoPlayCancel) + { + TRAP_IGNORE( iObserver->PlayCompleteL( aError ) ); + } + else + if ( !iRenderingSession) + { + if (iObserver) + { + TRAP_IGNORE( iObserver->PlayCompleteL( KErrNotReady ) ); + } + } + + if (iFileName) //if there is a pending item + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine, pending item" ); + TRAP_IGNORE( InitPlayL() ); + delete iFileName; + iFileName = NULL; + iVideoPlayCancel = EFalse; //no need to send StopL + } + else + if ( !iVideoPlayCancel) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine, no pending item" ); + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine, no cancellation from \ +video play" ); + TRAP( aError, iRenderingSession->PlayL() ); + //if play failed, send the result right way + if (aError && iObserver) + { + TRAP_IGNORE( iObserver->PlayCompleteL( aError ) ); + } + else + if (KErrNone == aError) + { + iRenderingSessionInUse = ETrue; + } + } + else + if (iVideoPlayCancel) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine, no pending item" ); + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine, stop previous \ +video item" ); + TRAP_IGNORE( iRenderingSession->StopL() ); + iRenderingSessionInUse = ETrue; + iVideoPlayCancel = EFalse; //StopL sent + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::ReleaseUpnpResourceL +// Release Upnp resouces +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::ReleaseUpnpResourceL() + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::ReleaseUpnpResourceL" ); + + // Inform the client about the connection lost + if (iObserver) + { + iObserver->ConnectionLostL(); + } + + // Stop the rendering session + if ( iRenderingSession && iAVController ) + { + //iRenderingSession->ReleaseLocalMSServicesL(); + iRenderingSession->RemoveObserver(); + iAVController->StopRenderingSession( *iRenderingSession); + iRenderingSession = NULL; + } + + // Disconnect UPnPAVController + delete iAVController; + iAVController = NULL; + + iRenderingSessionInUse = EFalse; + // Update engine state + iEngineState = /*EUPnPEngineConnectionLost;*/EUPnPEngineNotConnected; + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::WLANConnectionLost +// UPnP AV Controller calls this method to indicate that ... +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::WLANConnectionLost() + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::WLANConnectionLost" ); + + iFileSharingError = KErrDisconnected; + if ( iFileSharingActivationWaitNote ) + { + TRAP_IGNORE( iFileSharingActivationWaitNote->ProcessFinishedL() ); + } + TRAP_IGNORE( iCommonUI->DismissDialogL( KErrDisconnected ) ); + TRAP_IGNORE( ReleaseUpnpResourceL() ); + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::MediaRendererDisappeared +// Notifies that the Media Renderer we have a session with has disappeared. +// Session is now unusable and must be closed. +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::MediaRendererDisappeared( + TUPnPDeviceDisconnectedReason aReason) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::MediaRendererDisappeared" ); + + if (EDisconnected == aReason) + { + TRAP_IGNORE( ShowConnectionErrorL() ); + TRAP_IGNORE( ReleaseUpnpResourceL() ); + } + + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::InitialiseUserCounter +// Sets the initial value of the user counter to zero. +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::InitialiseUserCounter() + { + iNumberOfUsers = 0; + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::IncreaseUserCounter +// Increases the value of the user counter by one. +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::IncreaseUserCounter() + { + iNumberOfUsers++; + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::DecreaseUserCounter +// Decreases the value of the user counter by one. +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::DecreaseUserCounter() + { + iNumberOfUsers--; + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::UserCounter +// Gets the value of the user counter. +// -------------------------------------------------------------------------- +// +TInt CUPnPAiwEngine::UserCounter() const + { + return iNumberOfUsers; + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::StartTimer() +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::StartTimer() + { + // Stop the timer + StopTimer(); + + // Start the timer + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine, starting timer" ); + TRAPD( err, + iUPnPAiwTimer = CUPnPAiwTimer::NewL( KAiwTimerIntervalInSeconds, + this ) ) + ; + if (err) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine, timer start failed!" ); + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::StopTimer() +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::StopTimer() + { + // Stop the timer if it is running + if (iUPnPAiwTimer) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine, stopping timer" ); + delete iUPnPAiwTimer; + iUPnPAiwTimer = NULL; + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::TimerCallback +// Callback method for the UPnPAiWTimer. +// -------------------------------------------------------------------------- +// +EXPORT_C void CUPnPAiwEngine::TimerCallback() + { + StopTimer(); + if( iAVController ) + { + if( iRenderingSession ) + { + // Stop local file sharing + TRAP_IGNORE( iRenderingSession->ReleaseLocalMSServicesL() ); + + // Stop the rendering session + TRAP_IGNORE( iAVController->StopRenderingSession( + *iRenderingSession ) ); + iRenderingSession = NULL; + } + + // Disconnect UPnPAVController + delete iAVController; + iAVController = NULL; + + // Update engine state + iEngineState = EUPnPEngineNotConnected; + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::ShowConnectionErrorL() +// -------------------------------------------------------------------------- +// +EXPORT_C void CUPnPAiwEngine::ShowConnectionErrorL() + { + iCommonUI->DisplayConnectionErrorNoteL(); + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::ShowConnectionLostCopyErrorL() +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::ShowConnectionLostCopyErrorL() + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::ShowConnectionLostErrorL" ); + iCommonUI->DisplayConnectionLostCopyErrorNoteL(); + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::ShowTransferInfoNoteL +// Show correct info note after file transfer is completed. +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::ShowTransferInfoNoteL( + TUPnPAiwEngineTransferMode aMode, + TInt aCount, + const CUpnpAVDevice& aServerName ) const + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::ShowTransferInfoNoteL" ); + + // Converts device name into unicode string. + HBufC* deviceString = CnvUtfConverter::ConvertToUnicodeFromUtf8L( + aServerName.FriendlyName() ); + CleanupStack::PushL( deviceString ); + + HBufC* infoText= NULL; + if ( aCount == 1 ) + { + if ( aMode == EAiwEngineMove ) + { + // File moved. + infoText = StringLoader::LoadLC( + R_AIW_INFO_MOVE_EXT_ONE_TEXT, + *deviceString ); + } + else + { + // File copied. + infoText = StringLoader::LoadLC( + R_AIW_INFO_COPY_EXT_ONE_TEXT, + *deviceString ); + } + } + else + { + if ( aMode == EAiwEngineMove ) + { + // Files moved. + infoText = StringLoader::LoadLC( + R_AIW_INFO_MOVE_EXT_MANY_TEXT, + *deviceString, + aCount); + } + else + { + // Files copied. + infoText = StringLoader::LoadLC( + R_AIW_INFO_COPY_EXT_MANY_TEXT, + *deviceString, + aCount ); + } + } + + // Shows the dialog. + CAknInformationNote* infoNote = + new ( ELeave ) CAknInformationNote( ETrue ); + infoNote->ExecuteLD( *infoText ); + + CleanupStack::PopAndDestroy( infoText ); + CleanupStack::PopAndDestroy( deviceString ); + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::ReserveLocalMSServicesCompleted +// Notifies that the Media Server startup has completed. +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::ReserveLocalMSServicesCompleted(TInt aError) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::\ +ReserveLocalMSServicesCompleted" ); + + iFileSharingError = aError; + if (aError == KErrNone) + { + iLocalFileSharingActivated = ETrue; + } + if (iFileSharingActivationWaitNote) + { + TRAP_IGNORE( iFileSharingActivationWaitNote->ProcessFinishedL() ); + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::StartLocalFileSharingL +// Waits for local media server file sharing activation (or user cancel). +// -------------------------------------------------------------------------- +void CUPnPAiwEngine::StartLocalFileSharingL(MUPnPAVSessionBase *aSession) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::StartLocalFileSharingL" ); + + // Leave if the parameter is not valid + if ( !aSession) + { + User::Leave(KErrArgument); + } + + // Initialize the sharing error variable + iFileSharingError = KErrNone; + iLocalFileSharingActivated = EFalse; + + // Start the local media server + aSession->ReserveLocalMSServicesL(); + + // Instantiate and launch the wait note until the sharing is + // enabled of user cancels the operation + if ( !iLocalFileSharingActivated && iFileSharingError == KErrNone) + { + // Instantiate and launch the wait note until the sharing is + // enabled of user cancels the operation + iFileSharingActivationWaitNote = new(ELeave)CAknWaitDialog( + ( REINTERPRET_CAST( CEikDialog**, + &iFileSharingActivationWaitNote ) ), ETrue ); + iFileSharingActivationWaitNote->SetCallback( this); + TRAPD( fileSharingActivationError, + iFileSharingActivationWaitNote->ExecuteLD( + R_AIW_ENABLE_SHARING_WAIT_NOTE ) ) + ; + + // Cancel sharing activation is user pressed cancel + if (iFileSharingError == KErrCancel) + { + TRAP_IGNORE( aSession->CancelReserveLocalMSServicesL() ); + } + + // If sharing failed, and the user did not cancel the operations, + // forward the leave code. + if (fileSharingActivationError != KErrNone && iFileSharingError + != KErrCancel) + { + iFileSharingError = fileSharingActivationError; + } + } + + if (iFileSharingError != KErrNone) + { + User::Leave(iFileSharingError); + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::DialogDismissedL +// ProgressDialog call back method. Get's called when a dialog is +// dismissed. +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::DialogDismissedL(TInt aButtonId) + { + if (aButtonId == EAknSoftkeyCancel) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine, user cancelled the file \ +sharing activation" ); + iFileSharingError = KErrCancel; + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::DialogDismissedL +// Method for selecting a device. +// -------------------------------------------------------------------------- +// +CUpnpAVDevice* CUPnPAiwEngine::SelectDeviceL( + TUPnPDeviceTypesToSearch aDeviceType, TUPnPDialogTitle aDlgTitle) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::SelectDeviceL" ); + + CUpnpAVDevice* device= NULL; + + // Leave if the engine is not in right state + if ( !iAVController) + { + User::Leave(KErrNotReady); + } + else + { + // Create new UpnpAvDevice instance + device = CUpnpAVDevice::NewL(); + CleanupStack::PushL(device); + + // Do the device selection + TInt ret = iCommonUI->SelectDeviceL( *iAVController, *device, + aDeviceType, aDlgTitle); + + if (ret != KErrNone) + { + CleanupStack::PopAndDestroy(device); + device = NULL; + User::Leave(ret); + } + CleanupStack::Pop(device); // Will be returned from the method + } + + return device; + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::StarVideoPlayL +// Method for Playing a local video +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::StartVideoPlayL(const TDesC& aFileName) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::StartVideoPlayL" ); + + //check if selected renderer supports playing video + TInt status = KErrNone; + if (iRenderingSession->Device().VideoCapability() ) + { + // Launch the video player dialog to render the + // item on the selected rendering device. + MUPnPItemResolver* resolver = CreateResolverLC( aFileName ); + + // Update engine state + iEngineState = EUPnPEngineActive; + iRenderingSessionInUse = ETrue; + iVideoPlay = ETrue; + + status = iCommonUI->ExecuteVideoPlayerL( *iRenderingSession, + resolver->Item() ); + iVideoPlay = EFalse; + iRenderingSessionInUse = EFalse; + + if (KErrSessionClosed == status || KErrDisconnected == status) + { + if (KErrSessionClosed == status) + { + ReleaseUpnpResourceL(); + } + } + else + { + // Re-register to observe the rendering + // session and update engine state + iRenderingSession->RemoveObserver(); + iRenderingSession->SetObserver( *this); + iEngineState = EUPnPEngineConnected; + } + + //notify MG, the video playing is complete + if (iObserver) + { + iObserver->PlayCompleteL(status); + } + + if (KErrCancel == status) + { + TRAP_IGNORE( iRenderingSession->StopL() ); + iRenderingSessionInUse = ETrue; + iVideoPlayCancel = ETrue; + } + + CleanupStack::PopAndDestroy(); // resolver + } + else //if not + { + status = KErrNotSupported; + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::InitPlayL +// Method for Playing a local file +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::InitPlayL() + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::InitPlayL" ); + + //if pending an item + TInt error = KErrNone; + + if (iVideoPlay || iVideoPlayWait) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine, start video play" ); + TRAP_IGNORE( StartVideoPlayL( *iFileName ) ); + iVideoPlayWait = EFalse; + } + else + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine, start image play" ); + TRAP( error , CreateUpnpItemAndSetUriL( *iFileName ) ); + if (KErrNone == error) + { + iRenderingSessionInUse = ETrue; + } + else + { + iObserver->PlayCompleteL(error); + } + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::Wait +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::Wait() + { + StopWait(); + iWait.Start(); + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::StopWait +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::StopWait() + { + if (iWait.IsStarted() ) + { + if (iWait.CanStopNow() ) + { + iWait.AsyncStop(); + } + } + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::CreateUpnpItemAndSetUriL +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::CreateUpnpItemAndSetUriL(const TDesC& aFileName) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::CreateUpnpItemAndSetUriL" ); + + // Creates resolver to iResolver member variable. + MUPnPItemResolver* resolver = CreateResolverLC( aFileName ); + + // Sets uri. + const CUpnpElement& element = UPnPItemUtility::ResourceFromItemL( + iResolver->Item() ); + iRenderingSession->SetURIL( element.Value(), iResolver->Item() ); + + // Cleanup + CleanupStack::PopAndDestroy(); // resolver + + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::CreateUpnpItemAndSetUriL -END" ); + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::ResolveComplete +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::ResolveComplete( + const MUPnPItemResolver& /*aResolver*/, + TInt aError ) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::ResolveComplete" ); + + iResolveResult = aError; + StopWait(); + + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::ResolveComplete -END" ); + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::CreateResolverLC +// -------------------------------------------------------------------------- +// + MUPnPItemResolver* CUPnPAiwEngine::CreateResolverLC( const TDesC& aFilePath ) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::CreateResolverLC" ); + + // If member variable exists, resolving operation is ongoing. + if ( iResolver ) + { + User::Leave( KErrInUse ); + } + + // Creates resolver + TUPnPSelectDefaultResource selector; + iResolver = UPnPItemResolverFactory::NewLocalItemResolverL( + aFilePath, + *iAVController, + selector ); + CleanupStack::PushL( TCleanupItem( CleanupResolver, this ) ); + + // Starts async resolver. + iResolveResult = KErrNone; + iResolver->ResolveL( *this ); + Wait(); + + // If error occured, resolves it in here. It will cleanup resolver. + User::LeaveIfError( iResolveResult ); + + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::CreateResolverLC -END" ); + + return iResolver; + } + +// -------------------------------------------------------------------------- +// CUPnPAiwEngine::CleanupResolver +// Static method to cleanup resolver object. +// -------------------------------------------------------------------------- +// +void CUPnPAiwEngine::CleanupResolver( TAny* aAiwEngine ) + { + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::CleanupResolver" ); + + CUPnPAiwEngine* aiwEngine = reinterpret_cast( aAiwEngine ); + if ( aiwEngine ) + { + MUPnPItemResolver* tempResolver = aiwEngine->iResolver; + aiwEngine->iResolver = NULL; + delete tempResolver; + __LOG( "[UpnpAiwEngine]\t\t Resolver cleaned up." ); + } + + __LOG( "[UpnpAiwEngine]\t CUPnPAiwEngine::CleanupResolver -END" ); + } + +// End of file