--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/upnpframework/upnpcommonui/src/upnpselectiondialog.cpp Thu Dec 17 08:52:00 2009 +0200
@@ -0,0 +1,641 @@
+/*
+* Copyright (c) 2005-2006 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: Source file for UPnP Browse UI Implementation
+*
+*/
+
+
+// INCLUDE FILES
+// System
+#include <aknPopupHeadingPane.h>
+#include <aknPopup.h>
+#include <aknlists.h>
+#include <AknIconArray.h>
+#include <gulicon.h>
+#include <StringLoader.h>
+
+// upnp stack api
+#include <upnpstring.h>
+
+// upnpframework / avcontroller api
+#include "upnpavdevice.h"
+#include "upnpavcontroller.h"
+#include "upnpavcontrollerfactory.h"
+#include "upnpavdevicelist.h"
+#include "upnpavdevice.h"
+#include "upnpavcontroller.h"
+
+// upnpframework / internal api's
+#include "upnpcommonutils.h"
+
+// common ui internal
+#include <upnpcommonui.rsg>
+#include <upnpcommonui.mbg> //for icons
+#include "upnpselectiondialog.h"
+#include "upnpcommonui.h"
+
+// debug stuff
+_LIT( KComponentLogfile, "commonui.txt");
+#include "upnplog.h"
+
+// CONSTANTS
+_LIT( KAknCommonUIMbmFileName, "\\resource\\apps\\upnpcommonui.mbm" );
+const TInt KLength = 100;
+
+// --------------------------------------------------------------------------
+// CUPnPSelectionDialog::NewL
+// Two-phased constructor.
+// --------------------------------------------------------------------------
+CUPnPSelectionDialog* CUPnPSelectionDialog::NewL(
+ MUPnPAVController& aAVControl )
+ {
+ __LOG( "CUPnPSelectionDialog::NewL" );
+
+ CUPnPSelectionDialog* self =
+ new ( ELeave ) CUPnPSelectionDialog( aAVControl );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop();
+ return self;
+ }
+
+// --------------------------------------------------------------------------
+// CUPnPSelectionDialog::ConstructL
+// Symbian 2nd phase constructor can leave.
+// --------------------------------------------------------------------------
+void CUPnPSelectionDialog::ConstructL()
+ {
+ __LOG( "CUPnPSelectionDialog::ConstructL" );
+
+ iDeviceArray = CUpnpAVDeviceList::NewL();
+ // Register as an observer to device operations
+
+ iTypeOfDevicesToSearch = EUPnPSearchAllDevices;
+ }
+
+// --------------------------------------------------------------------------
+// CUPnPSelectionDialog::CUPnPSelectionDialog
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// --------------------------------------------------------------------------
+CUPnPSelectionDialog::CUPnPSelectionDialog( MUPnPAVController& aAVControl ):
+ iAVControl( aAVControl )
+ {
+ __LOG( "CUPnPSelectionDialog::CUPnPSelectionDialog" );
+
+ iDeviceObserver = iAVControl.DeviceObserver();
+ iAVControl.RemoveDeviceObserver();
+ iAVControl.SetDeviceObserver( *this );
+ iPopup = NULL;
+ iExitReason = KErrNone;
+ }
+
+// Destructor
+CUPnPSelectionDialog::~CUPnPSelectionDialog()
+ {
+ __LOG( "CUPnPSelectionDialog::~CUPnPSelectionDialog" );
+
+ delete iListBox;
+
+ // Unregister as an observer to device operations
+ iAVControl.RemoveDeviceObserver();
+ if( iDeviceObserver )
+ {
+ iAVControl.SetDeviceObserver( *iDeviceObserver );
+ }
+
+ delete iDeviceArray;
+ }
+
+// --------------------------------------------------------------------------
+// CUPnPSelectionDialog::PreLayoutDynInitL();
+// called by framework before dialog is shown
+// --------------------------------------------------------------------------
+void CUPnPSelectionDialog::PreLayoutDynInitL( const TDesC& aTitle )
+ {
+ __LOG( "CUPnPSelectionDialog::PreLayoutDynInitL" );
+
+ // Browse dialog title text
+ iPopup->SetTitleL( aTitle );
+
+ CAknIconArray* icons = new ( ELeave ) CAknIconArray(2);
+ CleanupStack::PushL( icons );
+
+ // Mif icons
+ MAknsSkinInstance* skin = AknsUtils::SkinInstance();
+ TFileName iconsPath( AknIconUtils::AvkonIconFileName( ) );
+
+ TFileName mbmFileName( KAknCommonUIMbmFileName );
+ TFileName dllName;
+ Dll::FileName( dllName );
+ TBuf<2> drive = dllName.Left( 2 ); // Drive letter followed by ':'
+ mbmFileName.Insert( 0, drive );
+
+ // Media server icon
+ AppendIconToArrayL( icons, skin,
+ mbmFileName,
+ KAknsIIDDefault,
+ EMbmUpnpcommonuiQgn_server_icon,
+ EMbmUpnpcommonuiQgn_server_icon_mask );
+ iListBox->ItemDrawer()->FormattedCellData()->SetIconArrayL( icons );
+ CleanupStack::Pop( icons );
+
+ // Enable horizontal scrolling
+ iListBox->ItemDrawer()->ColumnData()->EnableMarqueeL( ETrue );
+ LoadListItemsL();
+ }
+
+
+// --------------------------------------------------------------------------
+// CUPnPSelectionDialog::LoadListItemsL
+// Sends the browse request to UPnP AV Controller. When result set arrives,
+// UPnP AV Controller will call the "BrowseResultsL" call back method,
+// which is implemented below.
+// --------------------------------------------------------------------------
+void CUPnPSelectionDialog::LoadListItemsL()
+ {
+ __LOG( "CUPnPSelectionDialog::LoadListItemsL" );
+
+ CTextListBoxModel* model = iListBox->Model();
+ MDesCArray* textArray = model->ItemTextArray();
+ CDesCArray* listBoxItems = static_cast<CDesCArray*>( textArray );
+
+ //contents inside the array will be owned by iDeviceArray
+ CUpnpAVDeviceList* tempDeviceArray = NULL;
+ // Get the devices from the UPnP Stack according to the search criteria
+ if( iTypeOfDevicesToSearch == EUPnPSearchAllDevices )
+ {
+ CUpnpAVDeviceList* tempDeviceArray2 = NULL;
+ tempDeviceArray2 = iAVControl.GetMediaServersL();
+ if( tempDeviceArray2->Count() > 0 )
+ {
+ CleanupStack::PushL( tempDeviceArray2 );
+ CleanupStack::PushL( tempDeviceArray );
+ for( TInt i = 0; i < tempDeviceArray2->Count(); i++ )
+ {
+ tempDeviceArray->AppendDeviceL(
+ *( *tempDeviceArray2 )[i] );
+ }
+
+ CleanupStack::Pop( tempDeviceArray );
+ CleanupStack::Pop( tempDeviceArray2 );
+ tempDeviceArray2->Reset();
+
+ }
+
+ tempDeviceArray2 = iAVControl.GetMediaRenderersL();
+
+ if(tempDeviceArray2->Count() > 0 )
+ {
+ CleanupStack::PushL( tempDeviceArray2 );
+ CleanupStack::PushL( tempDeviceArray );
+ for( TInt i = 0; i < tempDeviceArray2->Count(); i++ )
+ {
+ tempDeviceArray->AppendDeviceL(
+ *( *tempDeviceArray2 )[i] );
+ }
+
+ CleanupStack::Pop( tempDeviceArray );
+ CleanupStack::Pop( tempDeviceArray2);
+ tempDeviceArray2->Reset();
+ }
+
+ delete tempDeviceArray2;
+
+ }
+ else if( iTypeOfDevicesToSearch == EUPnPSearchAllServerDevices ||
+ iTypeOfDevicesToSearch == EUPnPSearchServerDevicesWithCopyCapability ||
+ iTypeOfDevicesToSearch == EUPnPSearchServerDevicesWithSearchCapability )
+ {
+ tempDeviceArray = iAVControl.GetMediaServersL();
+ }
+ else
+ {
+ tempDeviceArray = iAVControl.GetMediaRenderersL();
+ }
+
+ CleanupStack::PushL( tempDeviceArray );
+ if ( tempDeviceArray->Count() )
+ {
+ for ( TInt i=0; i < tempDeviceArray->Count(); i++ )
+ {
+ // Check if the device match with the search criteria
+ if( MatchWithSearchCriteria(
+ const_cast<CUpnpAVDevice*>( ( *tempDeviceArray)[i] ) ) )
+ {
+ iDeviceArray->AppendDeviceL( *( *tempDeviceArray )[i] );
+ }
+ else
+ {
+ CUpnpAVDevice* tempDevice = ( *tempDeviceArray )[i];
+ delete tempDevice;
+ tempDevice = NULL;
+ }
+ }
+
+
+ for ( TInt i=0; i < iDeviceArray->Count(); i++ )
+ {
+ // Get device friendly name and replace illegal characters.
+ HBufC8* tmpfriendlyname =
+ UPnPCommonUtils::ReplaceIllegalFilenameCharactersL(
+ ( *iDeviceArray )[i]->FriendlyName().Left( KLength ) );
+ CleanupStack::PushL( tmpfriendlyname);
+
+ HBufC* device = UpnpString::ToUnicodeL( *tmpfriendlyname );
+ CleanupStack::PushL( device);
+
+ TBuf<KMaxFileName> item;
+ item.Format( _L( "%d\t%S\t\t" ),0, device );
+
+ CleanupStack::PopAndDestroy( device );
+ CleanupStack::PopAndDestroy( tmpfriendlyname );
+ listBoxItems->AppendL( item );
+ }
+
+ // Updates CBA.
+ UpdateCommandSetL();
+
+ iListBox->HandleItemAdditionL(); // Update listbox
+ iListBox->SetCurrentItemIndexAndDraw( 0 ); // select new item
+
+ }
+ else
+ {
+ HBufC* waitText = StringLoader::LoadLC(
+ R_UPNPCOMMONUI_EXTERNAL_WAITING_NOTE );
+ iListBox->View()->SetListEmptyTextL( *waitText );
+ CleanupStack::PopAndDestroy( waitText );
+ }
+
+ CleanupStack::Pop( tempDeviceArray );
+ tempDeviceArray->Reset();
+ delete tempDeviceArray;
+
+ }
+
+// --------------------------------------------------------------------------
+// CUPnPSelectionDialog::UPnPDeviceDiscovered
+// Returns discovered device from UPnP AV control point.
+// --------------------------------------------------------------------------
+void CUPnPSelectionDialog::UPnPDeviceDiscovered(
+ const CUpnpAVDevice& aDevice )
+ {
+ __LOG( "CUPnPSelectionDialog::UPnPDeviceDiscovered" );
+
+ TRAPD( error, UPnPDeviceDiscoveredL( aDevice ) );
+ if( error )
+ {
+ __LOG1( "UPnPDeviceDiscoveredL, leave %d .", error );
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CUPnPSelectionDialog::UPnPDeviceDiscoveredL
+// Returns discovered device from UPnP AV control point.
+// --------------------------------------------------------------------------
+void CUPnPSelectionDialog::UPnPDeviceDiscoveredL(
+ const CUpnpAVDevice& aDevice )
+ {
+ __LOG( "CUPnPSelectionDialog::UPnPDeviceDiscovered" );
+
+
+ if ( MatchWithSearchCriteria( const_cast<CUpnpAVDevice*>( &aDevice ) ) )
+ {
+ CUpnpAVDevice* tempDevice = CUpnpAVDevice::NewL( aDevice );
+ CleanupStack::PushL( tempDevice );
+ //ownership transferred
+ iDeviceArray->AppendDeviceL( *tempDevice );
+ CleanupStack::Pop( tempDevice );
+
+ HBufC8* tmpfriendlyname =
+ UPnPCommonUtils::ReplaceIllegalFilenameCharactersL(
+ ( ( CUpnpAVDevice* )tempDevice )->FriendlyName() );
+
+ CleanupStack::PushL( tmpfriendlyname );
+ TPtrC8 friendlyname = *tmpfriendlyname;
+
+ CTextListBoxModel* model = iListBox->Model();
+ MDesCArray* textArray = model->ItemTextArray();
+ CDesCArray* listBoxItems = static_cast<CDesCArray*>( textArray );
+ TBuf<KMaxFileName> item;
+ HBufC* tmpStr =
+ UpnpString::ToUnicodeL( friendlyname.Left( KLength ) );
+ CleanupStack::PushL( tmpStr );
+ item.Format( _L( "%d\t%S\t\t" ),0, tmpStr );
+ CleanupStack::PopAndDestroy( tmpStr );
+ CleanupStack::PopAndDestroy( tmpfriendlyname );
+ listBoxItems->AppendL( item );
+ iListBox->HandleItemAdditionL(); // Update listbox
+
+ // Updates CBA.
+ UpdateCommandSetL();
+
+ iListBox->ActivateL();
+ iListBox->DrawDeferred();
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CUPnPSelectionDialog::UPnPDeviceDisappeared
+// Returns disappeared device from UPnP AV control point.
+// --------------------------------------------------------------------------
+void CUPnPSelectionDialog::UPnPDeviceDisappeared(
+ const CUpnpAVDevice& aDevice )
+ {
+ __LOG( "CUPnPSelectionDialog::UPnPDeviceDisappeared" );
+
+ TRAPD( error, UPnPDeviceDisappearedL( aDevice ) );
+ if ( error )
+ {
+ __LOG1( "UPnPDeviceDisappearedL, leave %d", error );
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CUPnPSelectionDialog::UPnPDeviceDisappearedL
+// Returns disappeared device from UPnP AV control point.
+// --------------------------------------------------------------------------
+void CUPnPSelectionDialog::UPnPDeviceDisappearedL(
+ const CUpnpAVDevice& aDevice )
+ {
+ __LOG( "CUPnPSelectionDialog::UPnPDeviceDisappearedL" );
+
+ CTextListBoxModel* model = iListBox->Model();
+ TInt currentItem = iListBox->CurrentItemIndex();
+ MDesCArray* textArray = model->ItemTextArray();
+ CDesCArray* listBoxItems = static_cast<CDesCArray*>( textArray );
+ TInt i( 0 );
+ TPtrC8 ptr( aDevice.Uuid() );
+
+ while( i < iDeviceArray->Count() &&
+ ptr.Compare( ( *iDeviceArray )[i]->Uuid() ) )
+ {
+ i++;
+ }
+ if ( i < iDeviceArray->Count() )
+ {
+ iDeviceArray->RemoveAndDestroy( i );
+ listBoxItems->Delete( i, 1 );
+ AknListBoxUtils::HandleItemRemovalAndPositionHighlightL(
+ iListBox, currentItem, ETrue );
+ iListBox->DrawDeferred();
+ }
+
+ if ( !iDeviceArray->Count() )
+ {
+ // show "Waiting devices" text
+ HBufC* waitText = StringLoader::LoadLC(
+ R_UPNPCOMMONUI_EXTERNAL_WAITING_NOTE );
+ iListBox->View()->SetListEmptyTextL( *waitText );
+ CleanupStack::PopAndDestroy( waitText );
+
+ // Updates CBA.
+ UpdateCommandSetL();
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CUPnPSelectionDialog::WLANConnectionLost
+// --------------------------------------------------------------------------
+void CUPnPSelectionDialog::WLANConnectionLost()
+ {
+ __LOG( "CUPnPSelectionDialog::WLANConnectionLost" );
+ DismissItself( KErrDisconnected );
+ };
+
+// --------------------------------------------------------------------------
+// CUPnPSelectionDialog::AppendIconToArrayL
+// Load a possibly skinned icon (with mask) and append it to an
+// icon array.
+// --------------------------------------------------------------------------
+void CUPnPSelectionDialog::AppendIconToArrayL( CAknIconArray* aArray,
+ MAknsSkinInstance* aSkin,
+ const TDesC& aMbmFile,
+ const TAknsItemID& aID,
+ TInt aBitmapId,
+ TInt aMaskId )
+ {
+ __LOG( "CUPnPSelectionDialog::AppendIconToArrayL" );
+ __ASSERTD( aArray != NULL, __FILE__, __LINE__ );
+
+ CFbsBitmap* bitmap = NULL;
+ CFbsBitmap* mask = NULL;
+
+ AknsUtils::CreateIconLC( aSkin, aID,
+ bitmap, mask, aMbmFile, aBitmapId, aMaskId );
+
+ CGulIcon* icon = CGulIcon::NewL( bitmap, mask );
+ icon->SetBitmapsOwnedExternally( EFalse );
+
+ // icon now owns the bitmaps, no need to keep on cleanup stack.
+ CleanupStack::Pop( 2 ); // mask, bitmap
+ bitmap = NULL;
+ mask = NULL;
+
+ CleanupStack::PushL( icon );
+ aArray->AppendL( icon );
+
+ // aArray now owns the icon, no need to delete.
+ CleanupStack::Pop();
+ }
+
+// --------------------------------------------------------------------------
+// CUPnPSelectionDialog::CreatePopupL
+// Creates a selection popup.
+// --------------------------------------------------------------------------
+void CUPnPSelectionDialog::CreatePopupL(
+ const TDesC& aTitle,
+ TUPnPDeviceTypesToSearch aDeviceType )
+ {
+ __LOG( "CUPnPSelectionDialog::CreatePopupL" );
+
+ // Store the type of devices that are searched
+ iTypeOfDevicesToSearch = aDeviceType;
+
+ // Create and configure the list box
+ iListBox = new (ELeave) CAknSingleGraphicPopupMenuStyleListBox;
+ iPopup = CAknPopupList::NewL( iListBox,
+ R_UPNPCOMMONUI_SOFTKEYS_EMPTY_CANCEL,
+ AknPopupLayouts::EDynMenuWindow );
+ iListBox->ConstructL( iPopup, EAknListBoxSelectionList );
+ iListBox->CreateScrollBarFrameL( ETrue );
+ iListBox->ScrollBarFrame()->SetScrollBarVisibilityL(
+ CEikScrollBarFrame::EOff,
+ CEikScrollBarFrame::EAuto );
+ PreLayoutDynInitL( aTitle );
+ }
+
+// --------------------------------------------------------------------------
+// CUPnPSelectionDialog::StartPopupL
+// Parses the friendly names from the list of UPnPAVDevices and
+// executes the selection dialog. Returns ID of the selected item.
+// --------------------------------------------------------------------------
+TInt CUPnPSelectionDialog::StartPopupL( CUpnpAVDevice& aDevice )
+ {
+ __LOG( "CUPnPSelectionDialog::StartPopupL" );
+
+ TInt ret = KErrNone;
+
+ // Start animation
+ RDebug::Print( _L( "CUPnPSelectionDialog::\
+StartPopupL header animation" ) );
+ iPopup->Heading()-> SetHeaderAnimationL(
+ R_UPNPCOMMONUI_ANIMATION_FOR_SELECTION_DIALOG );
+
+ TInt popupOk = iPopup->ExecuteLD();
+ iPopup = NULL;
+ if ( popupOk )
+ {
+ if ( iListBox->CurrentItemIndex() >= 0 )
+ {
+ CUpnpAVDevice* device =
+ ( *iDeviceArray )[iListBox->CurrentItemIndex()];
+ aDevice.CopyFromL( *device );
+ ret = KErrNone;
+ }
+ }
+ else
+ {
+ if( KErrNone == iExitReason )
+ {
+ ret = KErrCancel;
+ }
+ else
+ {
+ ret = iExitReason;
+ }
+
+ }
+ return ret;
+ }
+
+
+// --------------------------------------------------------------------------
+// CUPnPSelectionDialog::DismissItself
+// Dismiss the selection dialog via an error code.
+// --------------------------------------------------------------------------
+void CUPnPSelectionDialog::DismissItself( TInt aError )
+ {
+ iExitReason = aError;
+ if( iPopup )
+ {
+ iPopup->CancelPopup();
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CUPnPSelectionDialog::MatchWithSearchCriteria
+// Checks if a given device matches with the search criteria.
+// --------------------------------------------------------------------------
+TBool CUPnPSelectionDialog::MatchWithSearchCriteria( CUpnpAVDevice *aDevice )
+ {
+ TBool returnValue = EFalse;
+ if( aDevice )
+ {
+ // If all device types are accepted
+ if( iTypeOfDevicesToSearch == EUPnPSearchAllDevices )
+ {
+ returnValue = ETrue;
+ }
+ // If all media server devices are accepted
+ else if( iTypeOfDevicesToSearch == EUPnPSearchAllServerDevices &&
+ aDevice->DeviceType() == CUpnpAVDevice::EMediaServer )
+ {
+ returnValue = ETrue;
+ }
+ // If all rendering devices are accepted
+ else if( iTypeOfDevicesToSearch == EUPnPSearchAllRenderingDevices &&
+ aDevice->DeviceType() == CUpnpAVDevice::EMediaRenderer )
+ {
+ returnValue = ETrue;
+ }
+ // If media server devices with copy capability are accepted
+ else if( iTypeOfDevicesToSearch ==
+ EUPnPSearchServerDevicesWithCopyCapability &&
+ aDevice->DeviceType() == CUpnpAVDevice::EMediaServer &&
+ aDevice->CopyCapability() )
+ {
+ returnValue = ETrue;
+ }
+ // If media server devices with search capability are accepted
+ else if( iTypeOfDevicesToSearch ==
+ EUPnPSearchServerDevicesWithSearchCapability &&
+ aDevice->DeviceType() == CUpnpAVDevice::EMediaServer &&
+ aDevice->SearchCapability() )
+ {
+ returnValue = ETrue;
+ }
+ // If rendering devices with image capability are accepted
+ else if( iTypeOfDevicesToSearch ==
+ EUPnPSearchRenderingDevicesWithImageCapability &&
+ aDevice->DeviceType() == CUpnpAVDevice::EMediaRenderer &&
+ aDevice->ImageCapability() )
+ {
+ returnValue = ETrue;
+ }
+ // If rendering devices with video capability are accepted
+ else if( iTypeOfDevicesToSearch ==
+ EUPnPSearchRenderingDevicesWithVideoCapability &&
+ aDevice->DeviceType() == CUpnpAVDevice::EMediaRenderer &&
+ aDevice->VideoCapability() )
+ {
+ returnValue = ETrue;
+ }
+ // If rendering devices with audio capability are accepted
+ else if( iTypeOfDevicesToSearch ==
+ EUPnPSearchRenderingDevicesWithAudioCapability &&
+ aDevice->DeviceType() == CUpnpAVDevice::EMediaRenderer &&
+ aDevice->AudioCapability() )
+ {
+ returnValue = ETrue;
+ }
+ else
+ {
+ returnValue = EFalse;
+ }
+ }
+ return returnValue;
+ }
+
+// --------------------------------------------------------------------------
+// CUPnPSelectionDialog::UpdateCommandSetL
+// Updates command set of the dialog by the search type of the devices.
+// --------------------------------------------------------------------------
+void CUPnPSelectionDialog::UpdateCommandSetL()
+ {
+ // Default values, used when no items in the list.
+ TInt resId = R_UPNPCOMMONUI_SOFTKEYS_EMPTY_CANCEL;
+ if ( iDeviceArray->Count() )
+ {
+ // Updates the commands set by iTypeOfDevicesToSearch variable.
+ switch( iTypeOfDevicesToSearch )
+ {
+ case EUPnPSearchServerDevicesWithCopyCapability:
+ // When copying or moving we should use "Ok" lsk
+ // instead of "Select".
+ resId = R_AVKON_SOFTKEYS_OK_CANCEL;
+ break;
+ default:
+ resId = R_AVKON_SOFTKEYS_SELECT_CANCEL;
+ break;
+ }
+ }
+
+ CEikButtonGroupContainer* bgc = iPopup->ButtonGroupContainer();
+ bgc->SetCommandSetL( resId );
+ bgc->DrawDeferred();
+ }
+
+// End of file