--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/videofeeds/mrssplugin/src/CIptv3XmlContentHandler.cpp Mon Jan 18 20:21:12 2010 +0200
@@ -0,0 +1,2679 @@
+/*
+* Copyright (c) 2007-2008 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: XML Parser handler*
+*/
+
+
+
+
+#include <e32base.h>
+#include "MIptvEpgVodCallback.h"
+#include "CIptvEpgCategory.h"
+#include "CIptvEpgContent.h"
+#include "IptvDebug.h"
+#include <xml/xmlparsererrors.h>
+#include <utf.h>
+#include "CIptvMediaContent.h"
+#include "CIptvTerminalVideoSupport.h"
+#include "CIptv3XmlContentHandler.h"
+#include "CIptvRssPlugin.h"
+#include "CIptvDownloadItem.h"
+#include "ciptvxmlconsts.h"
+#include "ciptvxmldatetime.h"
+
+// ======== MEMBER FUNCTIONS ========
+
+// --------------------------------------------------------------------------
+// Symbian 2nd phase constructor can leave.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::ConstructL()
+ {
+ iTerminalVideoSupport = CIptvTerminalVideoSupport::NewL();
+ }
+
+// --------------------------------------------------------------------------
+// Two-phased constructor.
+// Create instance of concrete interface implementation
+// --------------------------------------------------------------------------
+//
+CIptvXmlContentHandler* CIptvXmlContentHandler::NewL(
+ CIptvRssPlugin& aPlugin )
+ {
+ CIptvXmlContentHandler* self =
+ new ( ELeave ) CIptvXmlContentHandler( aPlugin );
+ CleanupStack::PushL( self );
+
+ self->ConstructL();
+
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// --------------------------------------------------------------------------
+// Destructor
+// --------------------------------------------------------------------------
+//
+CIptvXmlContentHandler::~CIptvXmlContentHandler()
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::~CIptvXmlContentHandler" );
+
+ delete iTerminalVideoSupport;
+
+ // Delete only if iChannelCategoryKey has the original value. Otherwise
+ // the iChannelCategory has been appended to iCategoryTable array.
+ // Deletingin this case leads to double deletion & crash. This happened
+ // when XML feed had an error in item and parsing was interrupted.
+ //
+ if ( 0 == iChannelCategoryKey )
+ {
+ delete iChannelCategory;
+ }
+ iChannelCategory = NULL;
+
+ delete iContent;
+ delete iBuffer;
+
+ iVodCallback = NULL;
+
+ iMediaContents.ResetAndDestroy();
+ iMediaContentSet.Close();
+ iCurrentCategoryKeys.Close();
+ iCategoryTable.ResetAndDestroy();
+ }
+
+// --------------------------------------------------------------------------
+// C++ default constructor
+// --------------------------------------------------------------------------
+//
+CIptvXmlContentHandler::CIptvXmlContentHandler( CIptvRssPlugin& aPlugin ) :
+ iPlugin( aPlugin ),
+ iState( EIptvRssIdleState ),
+ iMediaRatingScheme( EMediaRatingSimple ),
+ iCategoryState( ENoChannel )
+ {
+ }
+
+// --------------------------------------------------------------------------
+// Set callback for storing XML parse results.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::SetVodCallback(
+ MIptvEpgVodCallback* aVodCallback )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::SetVodCallback" );
+ iVodCallback = aVodCallback;
+ }
+
+// --------------------------------------------------------------------------
+// Callback to indicate the start of the document.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::OnStartDocumentL(
+ const RDocumentParameters& /*aDocParam*/,
+ TInt aErrorCode )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnStartDocumentL" );
+
+ if ( aErrorCode != KErrNone )
+ {
+ iPlugin.SetParsingFailed();
+ }
+
+ iServiceThumbnailAdded = EFalse;
+ iRSSContentFound = EFalse;
+ }
+
+// --------------------------------------------------------------------------
+// Callback to indicate the end of the document.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::OnEndDocumentL( TInt aErrorCode )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnEndDocumentL" );
+
+ AddCategories();
+
+ if ( ( KErrNone != aErrorCode ) || !iRSSContentFound )
+ {
+ iPlugin.SetParsingFailed();
+ }
+
+ iPlugin.ContentUpdateCompletedL();
+ }
+
+// --------------------------------------------------------------------------
+// Callback to indicate an element parsing start.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::OnStartElementL(
+ const RTagInfo& aElement,
+ const RAttributeArray& aAttributes,
+ TInt aErrorCode )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnStartElementL" );
+
+ if ( aErrorCode != KErrNone )
+ {
+ iPlugin.SetParsingFailed();
+ return;
+ }
+
+ delete iBuffer;
+ iBuffer = NULL;
+
+ TInt dataToCopy = Min(
+ aElement.LocalName().DesC().Length(),
+ KIptvRssItemNameMaxLength );
+ HBufC* name = HBufC::NewLC( dataToCopy );
+ TPtr localName = name->Des();
+ localName.Copy( aElement.LocalName().DesC().Mid( 0, dataToCopy ) );
+
+ // Parse name prefix.
+ iMediaPrefix = EFalse;
+ dataToCopy = Min(
+ aElement.Prefix().DesC().Length(),
+ KIptvRssItemNameMaxLength );
+ if ( 0 < dataToCopy )
+ {
+ HBufC* prefix = HBufC::NewLC( dataToCopy );
+ TPtr prefixName = prefix->Des();
+ prefixName.Copy( aElement.Prefix().DesC().Mid( 0, dataToCopy ) );
+ if ( prefixName.CompareF( KIptvRssMedia ) == 0 )
+ {
+ iMediaPrefix = ETrue;
+ }
+ CleanupStack::PopAndDestroy( prefix );
+ }
+
+ switch ( iState )
+ {
+ case EIptvRssIdleState:
+ {
+ if ( localName.CompareF( KIptvRssRss ) == 0 )
+ {
+ iState = EIptvRssState;
+ iRSSContentFound = ETrue;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssIdleState to EIptvRssState" );
+ HandleEnclosureL( aAttributes );
+ }
+ }
+ break;
+
+ case EIptvRssState:
+ {
+ if ( localName.CompareF( KIptvRssChannel ) == 0 )
+ {
+ if ( SetCategoryState( EChannelFound ) )
+ {
+ iState = EIptvRssChannelState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssState to EIptvRssChannelState" );
+ delete iChannelCategory;
+ iChannelCategory = NULL;
+ iChannelCategory = CreateCategoryL();
+ iChannelCategoryKey = 0;
+ }
+ }
+ }
+ break;
+
+ case EIptvRssChannelState:
+ {
+ //lint -e{961} Else block not needed, default is no operation.
+ if ( localName.CompareF( KIptvRssDescription ) == 0 )
+ {
+ iState = EIptvRssChannelDescriptionState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssChannelState to EIptvRssChannelDescriptionState" );
+ }
+ else if ( localName.CompareF( KIptvRssLink ) == 0 )
+ {
+ iState = EIptvRssChannelLinkState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssChannelState to EIptvRssChannelLinkState" );
+ }
+ else if ( localName.CompareF( KIptvRssTitle ) == 0 )
+ {
+ iState = EIptvRssChannelTitleState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssChannelState to EIptvRssChannelTitleState" );
+ }
+ else if ( localName.CompareF( KIptvRssImage ) == 0 )
+ {
+ iState = EIptvRssChannelImageState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssChannelState to EIptvRssChannelImageState" );
+ HandleEnclosureL( aAttributes );
+ }
+ else if ( localName.CompareF( KIptvRssItem ) == 0 )
+ {
+ iCurrentCategoryKeys.Reset();
+ SetCategoryState( EItemFound );
+ iState = EIptvRssItemState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssChannelState to EIptvRssItemState" );
+ CreateContentL();
+
+ iMediaDescriptionFixed = EFalse;
+ iMediaTitleFixed = EFalse;
+ iMediaRatingFixed = EFalse;
+ iMediaCopyrightFixed = EFalse;
+ iMediaThumbnailFixed = EFalse;
+ }
+ }
+ break;
+
+ case EIptvRssChannelImageState:
+ {
+ if ( localName.CompareF( KIptvRssUrl ) == 0 )
+ {
+ iState = EIptvRssChannelImageUrlState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssChannelImageState to EIptvRssChannelImageUrlState" );
+ }
+ }
+ break;
+
+ case EIptvRssChannelImageUrlState:
+ break;
+
+ case EIptvRssChannelDescriptionState:
+ break;
+
+ case EIptvRssChannelLinkState:
+ break;
+
+ case EIptvRssChannelTitleState:
+ break;
+
+ case EIptvRssItemState:
+ {
+ //lint -e{961} Else block not needed, default is no operation.
+ if ( localName.CompareF( KIptvRssDescription ) == 0 )
+ {
+ iState = EIptvRssItemDescriptionState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemState to EIptvRssItemDescriptionState" );
+ }
+ else if ( localName.CompareF( KIptvRssLink ) == 0 )
+ {
+ iState = EIptvRssItemLinkState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemState to EIptvRssItemLinkState" );
+ }
+ else if ( localName.CompareF( KIptvRssTitle ) == 0 )
+ {
+ iState = EIptvRssItemTitleState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemState to EIptvRssItemTitleState" );
+ }
+ else if ( localName.CompareF( KIptvRssEnclosure ) == 0 )
+ {
+ iState = EIptvRssItemEnclosureState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemState to EIptvRssItemEnclosureState" );
+ HandleEnclosureL( aAttributes );
+ }
+ else if ( localName.CompareF( KIptvRssGuid ) == 0 )
+ {
+ iState = EIptvRssItemGuidState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemState to EIptvRssItemGuidState" );
+ }
+ else if ( localName.CompareF( KIptvRssPubDate ) == 0 )
+ {
+ iState = EIptvRssItemPubDate;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemState to EIptvRssItemPubDate" );
+ }
+ else if ( localName.CompareF( KIptvRssThumbnail ) == 0 )
+ {
+ iState = EIptvRssItemMediaThumbnailState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemState to EIptvRssItemMediaThumbnailState" );
+ HandleEnclosureL( aAttributes );
+ }
+ else if ( localName.CompareF( KIptvRssMediaGroup ) == 0 )
+ {
+ iMediaGroup = ETrue;
+ iState = EIptvRssItemMediaGroupState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemState to EIptvRssItemMediaGroupState" );
+ }
+ else if ( localName.CompareF( KIptvRssMediaContent ) == 0 )
+ {
+ iMediaGroup = EFalse;
+ iState = EIptvRssItemMediaContentState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemState to EIptvRssItemMediaContentState" );
+ HandleEnclosureL( aAttributes );
+ }
+ else if ( localName.CompareF( KIptvRssAuthor ) == 0 )
+ {
+ iState = EIptvRssItemAuthorState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemState to EIptvRssItemAuthorState" );
+ }
+ else if ( localName.CompareF( KIptvRssMediaCopyright ) == 0 )
+ {
+ iState = EIptvRssItemMediaCopyrightState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemState to EIptvRssItemMediaCopyrightState" );
+ }
+ else if ( localName.CompareF( KIptvRssMediaRating ) == 0 )
+ {
+ iState = EIptvRssItemRatingState;
+ iMediaRatingScheme = EMediaRatingSimple;
+ HandleEnclosureL( aAttributes );
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemState to EIptvRssItemRatingState" );
+ }
+ else if ( localName.CompareF( KIptvRssMediaCategory ) == 0 )
+ {
+ if ( iMediaPrefix )
+ {
+ iState = EIptvRssItemMediaCategoryState;
+ HandleEnclosureL( aAttributes );
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemState to EIptvRssItemMediaCategoryState" );
+ }
+ }
+ }
+ break;
+
+ case EIptvRssItemDescriptionState:
+ break;
+
+ case EIptvRssItemLinkState:
+ break;
+
+ case EIptvRssItemTitleState:
+ break;
+
+ case EIptvRssItemGuidState:
+ break;
+
+ case EIptvRssItemMediaGroupState:
+ {
+ //lint -e{961} Else block not needed, default is no operation.
+ if ( localName.CompareF( KIptvRssDescription ) == 0 )
+ {
+ iState = EIptvRssItemDescriptionState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemMediaGroupState to EIptvRssItemDescriptionState" );
+ }
+ else if ( localName.CompareF( KIptvRssTitle ) == 0 )
+ {
+ iState = EIptvRssItemTitleState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemMediaGroupState to EIptvRssItemTitleState" );
+ }
+ else if ( localName.CompareF( KIptvRssMediaContent ) == 0 )
+ {
+ iState = EIptvRssItemMediaContentState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemMediaGroupState to EIptvRssItemMediaContentState" );
+ HandleEnclosureL( aAttributes );
+ }
+ else if ( localName.CompareF( KIptvRssThumbnail ) == 0 )
+ {
+ iState = EIptvRssItemMediaThumbnailState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemMediaGroupState to EIptvRssItemMediaThumbnailState" );
+ HandleEnclosureL( aAttributes );
+ }
+ else if ( localName.CompareF( KIptvRssMediaCopyright ) == 0 )
+ {
+ iState = EIptvRssItemMediaCopyrightState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemMediaGroupState to EIptvRssItemMediaCopyrightState" );
+ }
+ else if ( localName.CompareF( KIptvRssMediaRating ) == 0 )
+ {
+ iState = EIptvRssItemRatingState;
+ iMediaRatingScheme = EMediaRatingSimple;
+ HandleEnclosureL( aAttributes );
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemMediaGroupState to EIptvRssItemRatingState" );
+ }
+ else if ( localName.CompareF( KIptvRssMediaCategory ) == 0 )
+ {
+ if ( SetCategoryState( ECategoryFound ) )
+ {
+ iState = EIptvRssItemMediaCategoryState;
+ HandleEnclosureL( aAttributes );
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemMediaGroupState to EIptvRssItemMediaCategoryState" );
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ CleanupStack::PopAndDestroy( name );
+ name = NULL;
+
+ iMediaPrefix = EFalse;
+ }
+
+// --------------------------------------------------------------------------
+// Callback to indicate the element parsing completion.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::OnEndElementL(
+ const RTagInfo& aElement,
+ TInt aErrorCode )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnEndElementL" );
+
+ if ( aErrorCode != KErrNone )
+ {
+ iPlugin.SetParsingFailed();
+ return;
+ }
+
+ TInt dataToCopy = Min(
+ aElement.LocalName().DesC().Length(),
+ KIptvRssItemNameMaxLength );
+ HBufC* name = HBufC::NewLC( dataToCopy );
+ TPtr localName = name->Des();
+ localName.Copy( aElement.LocalName().DesC().Mid( 0, dataToCopy ) );
+
+ // Parse name prefix.
+ iMediaPrefix = EFalse;
+ dataToCopy = Min(
+ aElement.Prefix().DesC().Length(),
+ KIptvRssItemNameMaxLength );
+ if ( 0 < dataToCopy )
+ {
+ HBufC* prefix = HBufC::NewLC( dataToCopy );
+ TPtr prefixName = prefix->Des();
+ prefixName.Copy( aElement.Prefix().DesC().Mid( 0, dataToCopy ) );
+ if ( prefixName.CompareF( KIptvRssMedia ) == 0 )
+ {
+ iMediaPrefix = ETrue;
+ }
+ CleanupStack::PopAndDestroy( prefix );
+ }
+
+ switch ( iState )
+ {
+ case EIptvRssIdleState:
+ break;
+
+ case EIptvRssState:
+ {
+ if ( localName.CompareF( KIptvRssRss ) == 0 )
+ {
+ iState = EIptvRssIdleState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssState to EIptvRssIdleState" );
+ }
+ }
+ break;
+
+ case EIptvRssChannelState:
+ {
+ if ( localName.CompareF( KIptvRssChannel ) == 0 )
+ {
+ SetCategoryState( EChannelCompleted );
+ if ( 0 == iChannelCategoryKey )
+ {
+ // Channel category can be deleted when not used.
+ // Otherwise it has been appended to iCategoryTable and
+ // can not be deleted here.
+ delete iChannelCategory;
+ }
+ iChannelCategory = NULL;
+ iChannelCategoryKey = 0;
+ iState = EIptvRssState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssChannelState to EIptvRssState" );
+ }
+ }
+ break;
+
+ case EIptvRssChannelDescriptionState:
+ {
+ if ( localName.CompareF( KIptvRssDescription ) == 0 )
+ {
+ CompleteDescription();
+ iState = EIptvRssChannelState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssChannelDescriptionState to EIptvRssChannelState" );
+ }
+ }
+ break;
+
+ case EIptvRssChannelLinkState:
+ {
+ if ( localName.CompareF( KIptvRssLink ) == 0 )
+ {
+ CompleteLink();
+ iState = EIptvRssChannelState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssChannelLinkState to EIptvRssChannelState" );
+ }
+ }
+ break;
+
+ case EIptvRssChannelTitleState:
+ {
+ if ( localName.CompareF( KIptvRssTitle ) == 0 )
+ {
+ CompleteTitle();
+ iState = EIptvRssChannelState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssChannelTitleState to EIptvRssChannelState" );
+ }
+ }
+ break;
+
+ case EIptvRssChannelImageUrlState:
+ {
+ if ( localName.CompareF( KIptvRssUrl ) == 0 )
+ {
+ if ( iBuffer )
+ {
+ AddServiceToDlQueueL( iBuffer->Des() );
+ }
+
+ iState = EIptvRssChannelImageState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssChannelImageUrlState to EIptvRssChannelImageState" );
+ }
+ }
+ break;
+
+ case EIptvRssChannelImageState:
+ {
+ if ( localName.CompareF( KIptvRssImage ) == 0 )
+ {
+ iState = EIptvRssChannelState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssChannelImageState to EIptvRssChannelState " );
+ }
+ }
+ break;
+
+ case EIptvRssItemState:
+ {
+ if ( localName.CompareF( KIptvRssItem ) == 0 )
+ {
+ SetCategoryState( EItemCompleted );
+ PriorizeL();
+ if ( 0 == iCurrentCategoryKeys.Count() )
+ {
+ SetChannelCategoryL(); // default when others not set
+ }
+ AddContentL();
+
+ iMediaDescriptionFixed = EFalse;
+ iMediaTitleFixed = EFalse;
+ iMediaRatingFixed = EFalse;
+ iMediaCopyrightFixed = EFalse;
+ iMediaThumbnailFixed = EFalse;
+
+ iState = EIptvRssChannelState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemState to EIptvRssChannelState" );
+ }
+ }
+ break;
+
+ case EIptvRssItemDescriptionState:
+ {
+ if ( localName.CompareF( KIptvRssDescription ) == 0 )
+ {
+ CompleteDescription();
+ if ( iMediaGroup )
+ {
+ iState = EIptvRssItemMediaGroupState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemDescriptionState to EIptvRssItemMediaGroupState" );
+ }
+ else
+ {
+ iState = EIptvRssItemState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemDescriptionState to EIptvRssItemState" );
+ }
+ }
+ }
+ break;
+
+ case EIptvRssItemLinkState:
+ {
+ if ( localName.CompareF( KIptvRssLink ) == 0 )
+ {
+ CompleteLink();
+ iState = EIptvRssItemState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemLinkState to EIptvRssItemState" );
+ }
+ }
+ break;
+
+ case EIptvRssItemTitleState:
+ {
+ if ( localName.CompareF( KIptvRssTitle ) == 0 )
+ {
+ CompleteTitle();
+ if ( iMediaGroup )
+ {
+ iState = EIptvRssItemMediaGroupState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemTitleState to EIptvRssItemMediaGroupState" );
+ }
+ else
+ {
+ iState = EIptvRssItemState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemTitleState to EIptvRssItemState" );
+ }
+ }
+ }
+ break;
+
+ case EIptvRssItemEnclosureState:
+ {
+ if ( localName.CompareF( KIptvRssEnclosure ) == 0 )
+ {
+ iState = EIptvRssItemState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemEnclosureState to EIptvRssItemState" );
+ }
+ }
+ break;
+
+ case EIptvRssItemGuidState:
+ {
+ if ( localName.CompareF( KIptvRssGuid ) == 0 )
+ {
+ CompleteGuid();
+ iState = EIptvRssItemState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemGuidState to EIptvRssItemState" );
+ }
+ }
+ break;
+
+ case EIptvRssItemPubDate:
+ {
+ if ( localName.CompareF( KIptvRssPubDate ) == 0 )
+ {
+ CompletePubDate();
+ iState = EIptvRssItemState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemPubDate to EIptvRssItemState" );
+ }
+ }
+ break;
+
+ case EIptvRssItemMediaContentState:
+ {
+ if ( localName.CompareF( KIptvRssMediaContent ) == 0 )
+ {
+ if ( iMediaGroup )
+ {
+ iState = EIptvRssItemMediaGroupState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemMediaContentState to EIptvRssItemMediaGroupState" );
+ }
+ else
+ {
+ iMediaGroup = EFalse;
+ iState = EIptvRssItemState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemMediaContentState to EIptvRssItemState" );
+ }
+ }
+ }
+ break;
+
+ case EIptvRssItemMediaGroupState:
+ {
+ if ( localName.CompareF( KIptvRssMediaGroup ) == 0 )
+ {
+ iMediaGroup = EFalse;
+ iState = EIptvRssItemState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemMediaGroupState to EIptvRssItemState" );
+ }
+ }
+ break;
+
+ case EIptvRssItemMediaThumbnailState:
+ {
+ if ( localName.CompareF( KIptvRssThumbnail ) == 0 )
+ {
+ if ( iMediaGroup )
+ {
+ iState = EIptvRssItemMediaGroupState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemMediaThumbnailState to EIptvRssItemMediaGroupState" );
+ }
+ else
+ {
+ iMediaGroup = EFalse;
+ iState = EIptvRssItemState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemMediaThumbnailState to EIptvRssItemState" );
+ }
+ }
+ }
+ break;
+
+ case EIptvRssItemAuthorState:
+ {
+ if ( localName.CompareF( KIptvRssAuthor ) == 0 )
+ {
+ CompleteAuthor();
+ iState = EIptvRssItemState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemAuthorState to EIptvRssItemState" );
+ }
+ }
+ break;
+
+ case EIptvRssItemMediaCopyrightState:
+ {
+ if ( localName.CompareF( KIptvRssMediaCopyright ) == 0 )
+ {
+ CompleteCopyright();
+ if ( iMediaGroup )
+ {
+ iState = EIptvRssItemMediaGroupState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemMediaCopyrightState to EIptvRssItemMediaGroupState" );
+ }
+ else
+ {
+ iState = EIptvRssItemState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemMediaCopyrightState to EIptvRssItemState" );
+ }
+ }
+ }
+ break;
+
+ case EIptvRssItemRatingState:
+ {
+ if ( localName.CompareF( KIptvRssMediaRating ) == 0 )
+ {
+ CompleteRating();
+ if ( iMediaGroup )
+ {
+ iState = EIptvRssItemMediaGroupState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemRatingState to EIptvRssItemMediaGroupState" );
+ }
+ else
+ {
+ iState = EIptvRssItemState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemRatingState to EIptvRssItemState" );
+ }
+ }
+ }
+ break;
+
+ case EIptvRssItemMediaCategoryState:
+ {
+ if ( localName.CompareF( KIptvRssMediaCategory ) == 0 )
+ {
+ CompleteCategoryL();
+ if ( iMediaGroup )
+ {
+ iState = EIptvRssItemMediaGroupState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemMediaCategoryState to EIptvRssItemMediaGroupState" );
+ }
+ else
+ {
+ iState = EIptvRssItemState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemMediaCategoryState to EIptvRssItemState" );
+ }
+ }
+ }
+ break;
+
+ case EIptvRssItemMediaCategoryEnclosureState:
+ {
+ if ( localName.CompareF( KIptvRssMediaCategory ) == 0 )
+ {
+ // Category already got as label.
+ if ( iMediaGroup )
+ {
+ iState = EIptvRssItemMediaGroupState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemMediaCategoryEnclosureState to EIptvRssItemMediaGroupState" );
+ }
+ else
+ {
+ iState = EIptvRssItemState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemMediaCategoryEnclosureState to EIptvRssItemState" );
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ CleanupStack::PopAndDestroy( name );
+ name = NULL;
+
+ delete iBuffer;
+ iBuffer = NULL;
+
+ iMediaPrefix = EFalse;
+ }
+
+// --------------------------------------------------------------------------
+// Callback that sends the content of the element.
+// Not all the content may be returned in one go. The data may be sent in
+// chunks. When an OnEndElementL is received this means there is no more
+// content to be sent.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::OnContentL(
+ const TDesC8& aBytes,
+ TInt aErrorCode )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnContentL" );
+
+ if ( aErrorCode != KErrNone )
+ {
+ iPlugin.SetParsingFailed();
+ return;
+ }
+
+ // Number of new bytes.
+ TInt length = aBytes.Length();
+
+ HBufC* convBuf = HBufC::NewLC( length );
+ TPtr16 convPtr = convBuf->Des();
+
+ // Convert new bytes.
+ CnvUtfConverter::ConvertToUnicodeFromUtf8( convPtr, aBytes );
+
+ // Total number of bytes.
+ if ( iBuffer )
+ {
+ length = length + iBuffer->Length();
+ }
+
+ // Create new buffer.
+ HBufC* newBuf = HBufC::NewLC( length );
+ TPtr16 newPtr = newBuf->Des();
+
+ // Append and delete old buffer
+ if ( iBuffer )
+ {
+ newPtr.Append( iBuffer->Des() );
+ delete iBuffer;
+ iBuffer = NULL;
+ }
+
+ newPtr.Append( convPtr );
+ iBuffer = newBuf;
+
+ CleanupStack::Pop( newBuf );
+ CleanupStack::PopAndDestroy( convBuf );
+ convBuf = NULL;
+ }
+
+// --------------------------------------------------------------------------
+// Notification of the beginning of the scope of a prefix-URI Namespace
+// mapping.This method is always called before the corresponding
+// OnStartElementL method.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::OnStartPrefixMappingL(
+ const RString& /*aPrefix*/,
+ const RString& /*aUri*/,
+ TInt aErrorCode )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnStartPrefixMappingL" );
+
+ if ( aErrorCode != KErrNone )
+ {
+ iPlugin.SetParsingFailed();
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Notification of the end of the scope of a prefix-URI mapping.
+// This method is called after the corresponding DoEndElementL method.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::OnEndPrefixMappingL(
+ const RString& /*aPrefix*/,
+ TInt aErrorCode )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnEndPrefixMappingL" );
+
+ if ( aErrorCode != KErrNone )
+ {
+ iPlugin.SetParsingFailed();
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Notification of ignorable whitespace in element content.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::OnIgnorableWhiteSpaceL(
+ const TDesC8& /*aBytes*/,
+ TInt aErrorCode )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnIgnorableWhiteSpaceL" );
+
+ if ( aErrorCode != KErrNone )
+ {
+ iPlugin.SetParsingFailed();
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Notification of a skipped entity. If the parser encounters an
+// external entity it does not need to expand it - it can return the
+// entity as aName for the client to deal with.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::OnSkippedEntityL(
+ const RString& /*aName*/,
+ TInt aErrorCode )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnSkippedEntityL" );
+
+ if ( aErrorCode != KErrNone )
+ {
+ iPlugin.SetParsingFailed();
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Notification of a processing instruction.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::OnProcessingInstructionL(
+ const TDesC8& /*aTarget*/,
+ const TDesC8& /*aData*/,
+ TInt aErrorCode )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnProcessingInstructionL" );
+
+ if ( aErrorCode != KErrNone )
+ {
+ iPlugin.SetParsingFailed();
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Notification of XML file parsing is failure.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::OnError( TInt aErrorCode )
+ {
+ IPTVLOGSTRING_LOW_LEVEL( "RSS Plugin::CIptvXmlContentHandler::OnError" );
+
+ switch ( aErrorCode )
+ {
+ case EXmlParserError:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlParserError" );
+ break;
+
+ case EXmlSyntax:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlSyntax" );
+ break;
+
+ case EXmlNoElements:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlNoElements" );
+ break;
+
+ case EXmlInvalidToken:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlInvalidToken" );
+ break;
+
+ case EXmlUnclosedToken:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlUnclosedToken" );
+ break;
+
+ case EXmlPartialChar:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlPartialChar" );
+ break;
+
+ case EXmlTagMismatch:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlTagMismatch" );
+ break;
+
+ case EXmlDuplicateAttribute:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlDuplicateAttribute" );
+ break;
+
+ case EXmlJunkAfterDocElement:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlJunkAfterDocElement" );
+ break;
+
+ case EXmlPeRef:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlPeRef" );
+ break;
+
+ case EXmlUndefinedEntity:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlUndefinedEntity" );
+ break;
+
+ case EXmlRecursiveEntity:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlRecursiveEntity" );
+ break;
+
+ case EXmlAsyncEntity:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlAsyncEntity" );
+ break;
+
+ case EXmlBadCharRef:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlBadCharRef" );
+ break;
+
+ case EXmlBinaryEntityRef:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlBinaryEntityRef" );
+ break;
+
+ case EXmlAttributeExternalEntityRef:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlAttributeExternalEntityRef" );
+ break;
+
+ case EXmlMisplacedPi:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlMisplacedPi" );
+ break;
+
+ case EXmlUnknownEncoding:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlUnknownEncoding" );
+ break;
+
+ case EXmlIncorrectEncoding:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlIncorrectEncoding" );
+ break;
+
+ case EXmlUnclosedCdata:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlUnclosedCdata" );
+ break;
+
+ case EXmlExternalEntityHandling:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlExternalEntityHandling" );
+ break;
+
+ case EXmlNotStandalone:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlNotStandalone" );
+ break;
+
+ case EXmlUnexpectedState:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlUnexpectedState" );
+ break;
+
+ case EXmlEntityDeclInPe:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlEntityDeclInPe" );
+ break;
+
+ case EXmlDtdRequired:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlDtdRequired" );
+ break;
+
+ case EXmlFeatureLockedWhileParsing:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- EXmlFeatureLockedWhileParsing" );
+ break;
+
+ default:
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::OnError --- Unknown error" );
+ break;
+ }
+
+ iPlugin.SetParsingFailed();
+ }
+
+// --------------------------------------------------------------------------
+// Obtains the interface matching the specified uid.
+// --------------------------------------------------------------------------
+//
+TAny* CIptvXmlContentHandler::GetExtendedInterface( const TInt32 /*aUid*/ )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::GetExtendedInterface" );
+
+ return NULL;
+ }
+
+// --------------------------------------------------------------------------
+// Handles item copyright value.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::CompleteCopyright()
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::CompleteCopyright" );
+
+ if ( iBuffer )
+ {
+ // Media Description should override other Description values.
+ if ( iMediaPrefix || iMediaGroup || !iMediaCopyrightFixed )
+ {
+ TInt descLength = iBuffer->Length();
+ if ( iState == EIptvRssItemMediaCopyrightState )
+ {
+ TInt dataToCopy =
+ Min( descLength, KIptvEpgContentCopyrightLength );
+ if ( iContent )
+ {
+ iContent->iCopyright.Copy( iBuffer->Mid( 0, dataToCopy ) );
+ iMediaCopyrightFixed = iMediaPrefix || iMediaGroup;
+ }
+ }
+ }
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Handles parent rating value.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::CompleteRating()
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::CompleteRating" );
+
+ // Media Rating should override other Rating values.
+ if ( iBuffer && ( iMediaPrefix || iMediaGroup || !iMediaRatingFixed ) )
+ {
+ if ( iState == EIptvRssItemRatingState )
+ {
+ if ( EMediaRatingSimple == iMediaRatingScheme )
+ {
+ if ( 0 == iBuffer->CompareF( KIptvRssMediaAdult ) )
+ {
+ iContent->iRatingAge = KRatingAgeAdult;
+ }
+ else
+ {
+ iContent->iRatingAge = KRatingAgeUnlimited;
+ }
+ }
+ else if ( EMediaRatingNum == iMediaRatingScheme )
+ {
+ TBuf<KIptvMediaRatingAgeLength> ageValue;
+ TInt16 ratingAge( KRatingAgeUnlimited );
+ TInt dataToCopy( Min(
+ KIptvMediaRatingAgeLength, iBuffer->Length() ) );
+ ageValue.Copy( iBuffer->Mid( 0, dataToCopy ) );
+
+ if ( ageValue.Compare( KIptvEmptyDes ) != 0 )
+ {
+ TLex age( ageValue );
+ age.Val( ratingAge );
+ }
+
+ if ( KRatingAgeAdult < ratingAge )
+ {
+ iContent->iRatingAge = KRatingAgeAdult;
+ }
+ else if ( 0 > ratingAge )
+ {
+ iContent->iRatingAge = KRatingAgeUnlimited;
+ }
+ else
+ {
+ iContent->iRatingAge = ratingAge;
+ }
+ }
+ else
+ {
+ iContent->iRatingAge = KRatingAgeUnlimited;
+ }
+
+ iMediaRatingFixed = iMediaPrefix || iMediaGroup;
+ }
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Handles item category value.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::CompleteCategoryL()
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::CompleteCategoryL" );
+
+ if ( iBuffer )
+ {
+ if ( EIptvRssItemMediaCategoryState == iState )
+ {
+ SetItemCategoryL( iBuffer );
+ }
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Handles item category value.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::CompleteCategoryL( const HBufC* aName )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::CompleteCategoryL" );
+
+ if ( aName )
+ {
+ if ( EIptvRssItemMediaCategoryEnclosureState == iState )
+ {
+ SetItemCategoryL( aName );
+ }
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Handles item author value.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::CompleteAuthor()
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::CompleteAuthor" );
+
+ if ( iBuffer )
+ {
+ TInt descLength = iBuffer->Length();
+ if ( iState == EIptvRssItemAuthorState )
+ {
+ TInt dataToCopy = Min( descLength, KIptvEpgContentAuthorLength );
+ if ( iContent )
+ {
+ iContent->iAuthor.Copy( iBuffer->Mid( 0, dataToCopy ) );
+ }
+ }
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Handles item and category description value.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::CompleteDescription()
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::CompleteDescription" );
+
+ if ( iBuffer )
+ {
+ TInt descLength = iBuffer->Length();
+ //lint -e{961} Else block not needed, default is no operation.
+ if ( iState == EIptvRssChannelDescriptionState )
+ {
+ TInt dataToCopy =
+ Min( descLength, KIptvEpgCategoryDescriptionMaxLength );
+ if ( iChannelCategory )
+ {
+ iChannelCategory->iDescription.Copy(
+ iBuffer->Mid( 0, dataToCopy ) );
+ }
+ }
+ else if ( iState == EIptvRssItemDescriptionState )
+ {
+ // Media Description should override other Description values.
+ if ( iMediaPrefix || iMediaGroup || !iMediaDescriptionFixed )
+ {
+ TInt dataToCopy =
+ Min( descLength, KIptvEpgContentDescriptionMaxLength );
+ if ( iContent )
+ {
+ iContent->iDescription.Copy(
+ iBuffer->Mid( 0, dataToCopy ) );
+ iMediaDescriptionFixed = iMediaPrefix || iMediaGroup;
+ }
+ }
+ }
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Handles item and category title value.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::CompleteTitle()
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::CompleteTitle" );
+
+ if ( iBuffer )
+ {
+ TInt descLength = iBuffer->Length();
+ //lint -e{961} Else block not needed, default is no operation.
+ if ( iState == EIptvRssChannelTitleState )
+ {
+ TInt dataToCopy =
+ Min( descLength , KIptvEpgCategoryNameMaxLength );
+ if ( iChannelCategory )
+ {
+ iChannelCategory->iName.Copy(
+ iBuffer->Mid( 0, dataToCopy ) );
+ }
+ }
+ else if ( iState == EIptvRssItemTitleState )
+ {
+ // Media Title should override other Title values.
+ if ( iMediaPrefix || iMediaGroup || !iMediaTitleFixed )
+ {
+ TInt dataToCopy =
+ Min( descLength, KIptvEpgContentNameMaxLength );
+ if ( iContent )
+ {
+ iContent->iName.Copy( iBuffer->Mid( 0, dataToCopy ) );
+ iMediaTitleFixed = iMediaPrefix || iMediaGroup;
+ }
+ }
+ }
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Handles item url link value.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::CompleteLink()
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::CompleteLink" );
+
+ if ( iBuffer )
+ {
+ TInt descLength = iBuffer->Length();
+ if ( iState == EIptvRssItemLinkState )
+ {
+ if ( iContent )
+ {
+ TInt dataToCopy = Min(
+ descLength,
+ KIptvEpgContentBrowserUrlMaxLength );
+
+ if ( dataToCopy <= KIptvUrlMaxLength )
+ {
+ iContent->iBrowserUrl.Copy( iBuffer->Mid( 0, dataToCopy ) );
+ }
+ }
+ }
+ }
+ }
+
+
+// --------------------------------------------------------------------------
+// Handles item publish time value.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::CompletePubDate()
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::CompletePubDate" );
+
+ if ( iState == EIptvRssItemPubDate )
+ {
+ TTime time;
+ TRAPD( error, CIptvXmlDateTime::ParseGmtL( iBuffer, time ) );
+ if ( error == KErrNone )
+ {
+ if ( iContent )
+ {
+ iContent->iPubDate = time;
+ }
+ }
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Handles item guid value.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::CompleteGuid()
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::CompleteGuid" );
+
+ if ( iBuffer )
+ {
+ TInt descLength = iBuffer->Length();
+ if ( iState == EIptvRssItemGuidState )
+ {
+ if ( iContent )
+ {
+ TInt dataToCopy = Min( descLength, KIptvIdMaxLength );
+ iContent->iId.Copy( iBuffer->Right( dataToCopy ) );
+ }
+ }
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Handles element attributes.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::HandleEnclosureL(
+ const RAttributeArray& aAttributeList )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::HandleEnclosureL" );
+
+ CIptvMediaContent* content( CIptvMediaContent::NewL() );
+ CleanupStack::PushL( content );
+
+ TInt count = aAttributeList.Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ // Name
+ const RTagInfo& tag = aAttributeList[i].Attribute();
+ const TDesC8& n = tag.LocalName().DesC();
+ TInt dataToCopy = Min( n.Length(), KIptvRssItemNameMaxLength );
+ HBufC* name = HBufC::NewLC( dataToCopy );
+ TPtr namePtr = name->Des();
+ namePtr.Copy( n.Mid( 0, dataToCopy ) );
+
+ // Value
+ const TDesC8& v = aAttributeList[i].Value().DesC();
+ dataToCopy =
+ Min( v.Length(), KIptvRssEnclosureParameterMaxValueLength );
+ HBufC* value = HBufC::NewLC( dataToCopy );
+ TPtr valuePtr = value->Des();
+ valuePtr.Copy( v.Mid( 0, dataToCopy ) );
+
+ TInt valueLength = valuePtr.Length();
+
+ // RSS 2.0
+ //lint -e{961} Else block not needed, default is no operation.
+ if ( iState == EIptvRssItemEnclosureState )
+ {
+ if ( iContent )
+ {
+ // Url
+ //lint -e{961} Else block not needed, default is no operation.
+ if ( namePtr.CompareF( KIptvRssUrl ) == 0 &&
+ valueLength <= KIptvUrlMaxLength )
+ {
+ content->SetMediaContentUrlL( valuePtr );
+ content->iExpression = CIptvMediaContent::EFull;
+
+ // Set download type according protocol,
+ // mime-type can change this later
+ if ( valuePtr.Left( KIptvProtocolNameLength ).CompareF(
+ KIptvRssHttp ) == 0 )
+ {
+ content->iDownloadType = EIptvDownloadTypeImmediate;
+ }
+ else if ( valuePtr.Left( KIptvProtocolNameLength ).CompareF(
+ KIptvRssRtsp ) == 0 )
+ {
+ content->iDownloadType = EIptvDownloadTypeStream;
+ }
+ }
+ // Type
+ else if ( namePtr.CompareF( KIptvRssType ) == 0 )
+ {
+ dataToCopy = Min( valueLength, KIptvCAMimeTypeLength );
+ content->iMimeType.Copy( valuePtr.Mid( 0, dataToCopy ) );
+ }
+ // Length
+ else if ( namePtr.CompareF( KIptvRssLength ) == 0 )
+ {
+ if ( valuePtr.Compare( KIptvEmptyDes ) != 0 )
+ {
+ TLex l( valuePtr );
+ l.Val( content->iFileSize, EDecimal );
+ }
+ }
+ }
+ }
+ else if ( iState == EIptvRssChannelImageState )
+ {
+ if ( namePtr.CompareF( KIptvRssHref ) == 0 )
+ {
+ AddServiceToDlQueueL( valuePtr );
+ }
+ }
+ else if ( iState == EIptvRssState )
+ {
+ if ( namePtr.CompareF( KIptvRssMedia ) == 0 )
+ {
+ if ( valuePtr.CompareF( KIptvYahooRss ) == 0 )
+ {
+ iYahoo = ETrue;
+ }
+ }
+ }
+ // Yahoo media RSS
+ else if ( iState == EIptvRssItemMediaThumbnailState )
+ {
+ // Media Description should override other Description values.
+ if ( iMediaPrefix || iMediaGroup || !iMediaThumbnailFixed )
+ {
+ if ( namePtr.CompareF( KIptvRssUrl ) == 0 &&
+ valueLength <= KIptvUrlMaxLength )
+ {
+ dataToCopy =
+ Min( valueLength, KIptvEpgContentIconFilePathMaxLength );
+ iContent->iIconFilePath.Copy( valuePtr.Mid( 0, dataToCopy ) );
+ iContent->iIsIconFilePathUrl = ETrue;
+ iMediaThumbnailFixed = iMediaPrefix || iMediaGroup;
+ }
+ }
+ }
+ else if ( iState == EIptvRssItemMediaContentState )
+ {
+ if ( iContent )
+ {
+ // url
+ //lint -e{961} Else block not needed, default is no operation.
+ if ( namePtr.CompareF( KIptvRssUrl ) == 0 &&
+ valueLength <= KIptvUrlMaxLength )
+ {
+ content->SetMediaContentUrlL( valuePtr );
+
+ // Set download type according protocol,
+ // mime-type can change this later
+ if ( valuePtr.Left( KIptvProtocolNameLength ).CompareF(
+ KIptvRssHttp ) == 0 )
+ {
+ content->iDownloadType = EIptvDownloadTypeImmediate;
+ }
+ else if ( valuePtr.Left( KIptvProtocolNameLength ).CompareF(
+ KIptvRssRtsp ) == 0 )
+ {
+ content->iDownloadType = EIptvDownloadTypeStream;
+ }
+ }
+ // filesize
+ else if ( namePtr.CompareF( KIptvRssMediaFileSize ) == 0 )
+ {
+ if ( valuePtr.Compare( KIptvEmptyDes ) != 0 )
+ {
+ TLex l( valuePtr );
+ l.Val( content->iFileSize, EDecimal );
+ }
+ }
+ // mime-type
+ else if ( namePtr.CompareF( KIptvRssType ) == 0 )
+ {
+ dataToCopy = Min( valueLength, KIptvCAMimeTypeLength );
+ content->iMimeType.Copy( valuePtr.Mid( 0, dataToCopy ) );
+ }
+ // medium
+ else if ( namePtr.CompareF( KIptvRssMediaMedium ) == 0 )
+ {
+ dataToCopy = Min( valueLength, KIptvMediumMaxLength );
+ content->iMedium.Copy( valuePtr.Mid( 0, dataToCopy ) );
+ }
+ // isDefault
+ else if ( namePtr.CompareF( KIptvRssMediaIsDefault ) == 0 )
+ {
+ if ( valuePtr.CompareF( KIptvTrue ) == 0 )
+ {
+ content->iIsDefault = ETrue;
+ }
+ else
+ {
+ content->iIsDefault = EFalse;
+ }
+ }
+ // expression
+ else if ( namePtr.CompareF( KIptvRssMediaExpression ) == 0 )
+ {
+ if ( valuePtr.CompareF( KIptvRssMediaSample ) == 0 )
+ {
+ content->iExpression = CIptvMediaContent::ESample;
+ }
+ else if ( valuePtr.CompareF( KIptvRssMediaFull ) == 0 )
+ {
+ content->iExpression = CIptvMediaContent::EFull;
+ }
+ else if ( valuePtr.CompareF( KIptvRssMediaNonStop ) == 0 )
+ {
+ content->iExpression = CIptvMediaContent::ENonStop;
+ }
+ else
+ {
+ content->iExpression = CIptvMediaContent::EFull;
+ }
+ }
+ // bitrate
+ else if ( namePtr.CompareF( KIptvRssMediaBitrate ) == 0 )
+ {
+ TInt bitrate = 0;
+ if ( valuePtr.Compare( KIptvEmptyDes ) != 0 )
+ {
+ TLex l( valuePtr );
+ l.Val( bitrate );
+ }
+
+ if ( 0 < bitrate )
+ {
+ content->iBitrate = bitrate;
+ }
+ }
+ // framerate
+ else if ( namePtr.CompareF( KIptvRssMediaFramerate ) == 0 )
+ {
+ TInt framerate = 0;
+ if ( valuePtr.Compare( KIptvEmptyDes ) != 0 )
+ {
+ TLex l( valuePtr );
+ l.Val( framerate );
+ }
+
+ if ( 0 < framerate )
+ {
+ content->iFramerate = framerate;
+ }
+ }
+ // samplingrate
+ else if ( namePtr.CompareF( KIptvRssMediaSamplingrate ) == 0 )
+ {
+ TInt samplingrate = 0;
+ if ( valuePtr.Compare( KIptvEmptyDes ) != 0 )
+ {
+ TLex l( valuePtr );
+ l.Val( samplingrate );
+ }
+
+ if ( 0 < samplingrate )
+ {
+ content->iSamplingrate = samplingrate;
+ }
+ }
+ // duration
+ else if ( namePtr.CompareF( KIptvRssMediaDuration ) == 0 )
+ {
+ TInt duration = 0;
+ if ( valuePtr.Compare( KIptvEmptyDes ) != 0 )
+ {
+ TLex l( valuePtr );
+ l.Val( duration );
+ }
+
+ if ( 0 < duration )
+ {
+ content->iDuration = duration;
+ }
+ }
+ // height
+ else if ( namePtr.CompareF( KIptvRssMediaHeight ) == 0 )
+ {
+ TInt height = 0;
+ if ( valuePtr.Compare( KIptvEmptyDes ) != 0 )
+ {
+ TLex l( valuePtr );
+ l.Val( height );
+ }
+
+ if ( 0 < height )
+ {
+ content->iHeight = height;
+ }
+ }
+ // width
+ else if ( namePtr.CompareF( KIptvRssMediaWidth ) == 0 )
+ {
+ TInt width = 0;
+ if ( valuePtr.Compare( KIptvEmptyDes ) != 0 )
+ {
+ TLex l( valuePtr );
+ l.Val( width );
+ }
+
+ if ( 0 < width )
+ {
+ content->iWidth = width;
+ }
+ }
+ // language
+ else if ( namePtr.CompareF( KIptvRssMediaLanguage ) == 0 )
+ {
+ dataToCopy = Min( valueLength, KIptvCALanguageLength );
+ content->iLanguage.Copy( valuePtr.Mid( 0, dataToCopy ) );
+ }
+ }
+ }
+ else if ( EIptvRssItemRatingState == iState )
+ {
+ if ( 0 == namePtr.CompareF( KIptvRssMediaRatingScheme ) )
+ {
+ if ( 0 == valuePtr.CompareF( KIptvRssMediaRatingSchemeSimple ) )
+ {
+ iMediaRatingScheme = EMediaRatingSimple;
+ }
+ else if ( 0 == valuePtr.CompareF( KIptvRssMediaRatingSchemeNum ) )
+ {
+ iMediaRatingScheme = EMediaRatingNum;
+ }
+ else
+ {
+ iMediaRatingScheme = EMediaRatingSimple;
+ }
+ }
+ }
+ else if ( EIptvRssItemMediaCategoryState == iState )
+ {
+ if ( 0 == namePtr.CompareF( KIptvRssMediaLabel ) )
+ {
+ iState = EIptvRssItemMediaCategoryEnclosureState;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::State changed from EIptvRssItemMediaCategoryState to EIptvRssItemMediaCategoryEnclosureState" );
+ CompleteCategoryL( value );
+ }
+ }
+
+ // Value and Name.
+ CleanupStack::PopAndDestroy( KIptvPopValueAndName, name );
+ value = NULL;
+ name = NULL;
+ }
+
+ if ( content )
+ {
+ // Check that URL is not empty
+ if ( content->GetMediaContentUrl().Length() > 0 )
+ {
+ SetDownloadTypeFromMimeType( *content );
+ content->PrintL();
+ iMediaContents.AppendL( content );
+ CleanupStack::Pop( content );
+ }
+ else
+ {
+ CleanupStack::PopAndDestroy( content );
+ content = NULL;
+ }
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Create a new category descriptor.
+// --------------------------------------------------------------------------
+//
+CIptvEpgCategory* CIptvXmlContentHandler::CreateCategoryL() const
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::CreateCategoryL" );
+
+ CIptvEpgCategory* category( NULL );
+
+ category = CIptvEpgCategory::NewL();
+
+ // Key is auto-increment
+
+ // Parent key
+ category->iParentKey = KIptvVodContentCategoryRootId;
+
+ // Id
+ category->iId = KIptvEmptyDes;
+
+ // Name
+ category->iName = KIptvEmptyDes;
+
+ // Icon file Id
+ category->iIconFileId = 0; // Obsolete field
+
+ // Is icon file path URL
+ category->iIsIconFilePathUrl = ETrue; // Obsolete field
+
+ // Icon file path
+ category->iIconFilePath = KIptvEmptyDes; // Obsolete field
+
+ // Description
+ category->iDescription = KIptvEmptyDes;
+
+ // Item count
+ category->iContentCount = 0;
+
+ return category;
+ }
+
+// --------------------------------------------------------------------------
+// Set a category for current item.
+// When category has been used for some other item it already exists and
+// is restored, Otherwise a new one is created and a key value given.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::SetItemCategoryL( const HBufC* aName )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::SetItemCategoryL" );
+
+ // When no name defined, retain default category.
+ if ( aName )
+ {
+ if ( 0 < aName->Length() )
+ {
+ TUint32 categoryKey( 0 );
+ TInt categoryCount = iCategoryTable.Count();
+
+ // Name of the Category candidate.
+ HBufC* name = HBufC::NewLC( KIptvEpgCategoryNameMaxLength );
+ TPtr16 namePtr = name->Des();
+ TInt dataToCopy =
+ Min( aName->Length(), KIptvEpgCategoryNameMaxLength );
+ namePtr.Copy( aName->Mid( 0, dataToCopy ) );
+
+ // Search category whether already exist.
+ for ( TInt i = 0; ( i < categoryCount ) && ( 0 == categoryKey ); i++ )
+ {
+ if ( 0 == iCategoryTable[i]->iName.CompareF( namePtr ) )
+ {
+ categoryKey = i + 1;
+ }
+ }
+
+ if ( 0 != categoryKey )
+ {
+ // Whether category alreaady exists, add its key for content.
+ // Avoid double linking.
+ if ( 0 != iCurrentCategoryKeys.Find( categoryKey ) )
+ {
+ iCurrentCategoryKeys.AppendL( categoryKey );
+ }
+ }
+ else if ( iCategoryCount < KIptvEpgMaxCategoryCount )
+ {
+ // Whether category not yet exists, add a new one.
+ CIptvEpgCategory* newCategory = CreateCategoryL();
+ CleanupStack::PushL( newCategory );
+
+ // Use defaults from channel category.
+ if ( newCategory )
+ {
+ newCategory->iName.Copy( namePtr );
+ if ( iChannelCategory )
+ {
+ newCategory->iDescription.Copy(
+ iChannelCategory->iDescription );
+ }
+
+ iCategoryTable.AppendL( newCategory );
+ iCurrentCategoryKeys.AppendL( iCategoryTable.Count() );
+ }
+
+ CleanupStack::Pop( newCategory );
+ }
+ else
+ {
+ // New category can not be set, retain selection before.
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::SetItemCategoryL -- Category limit reached! Category not added!" );
+ }
+
+ CleanupStack::PopAndDestroy( name );
+ name = NULL;
+ }
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Set channel as default category for current Item.
+// When channel category has already been used, restore it,
+// Otherwise save it and give a key value.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::SetChannelCategoryL()
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::SetChannelCategoryL" );
+
+ if ( iChannelCategory )
+ {
+ // Check whether channel category has not yet already been used.
+ if ( ( 0 == iChannelCategoryKey ) &&
+ ( iCategoryCount < KIptvEpgMaxCategoryCount ) )
+ {
+ iCategoryTable.AppendL( iChannelCategory );
+ iChannelCategoryKey = iCategoryTable.Count();
+ }
+
+ // Add key for current item content.
+ if ( 0 != iChannelCategoryKey )
+ {
+ iCurrentCategoryKeys.AppendL( iChannelCategoryKey );
+ }
+ else
+ {
+ // Channel category can not be set, retain selection before.
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::SetChannelCategoryL -- Category limit reached! Category not added!" );
+ }
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Stores all categories used by current itam to database.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::AddCategories()
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::AddCategories" );
+
+ TInt categoryCount( iCategoryTable.Count() );
+
+ for ( TInt i = 0; i < categoryCount; i++ )
+ {
+ TUint32 newKey( 0 );
+
+#ifdef _DEBUG
+ TBuf<KIptvEpgCategoryNameMaxLength + 1> name;
+ name.Zero();
+ name.Copy( iCategoryTable[i]->iName );
+
+ IPTVLOGSTRING3_LOW_LEVEL(
+ "RSS Plugin::AddCategories Category '%S' added with %d items",
+ &name,
+ iCategoryTable[i]->iContentCount );
+#endif
+
+ TRAPD(
+ error,
+ iVodCallback->AddCategoryL( *( iCategoryTable[i] ), newKey ) );
+ //lint -e{961} Else block not needed, only error handling here.
+ if ( KErrNone != error )
+ {
+ IPTVLOGSTRING2_LOW_LEVEL( "RSS Plugin::AddCategories Error = %d",
+ error );
+ }
+ else if ( newKey != ( i + 1 ) )
+ {
+ IPTVLOGSTRING3_LOW_LEVEL(
+ "RSS Plugin::AddCategories Unexpected key %d, %d expected",
+ newKey, i + 1 );
+ }
+ }
+
+ // Categories saved to database, descriptors no more needed.
+ iCategoryTable.ResetAndDestroy();
+ if ( iChannelCategory && ( 0 == iChannelCategoryKey ) )
+ {
+ // Current channel category is not included to iCategoryTable and
+ // so has not been deleted above.
+ delete iChannelCategory;
+ }
+ iChannelCategory = NULL;
+ iChannelCategoryKey = 0;
+ iCurrentCategoryKeys.Reset();
+ }
+
+// --------------------------------------------------------------------------
+// Add current content to dabase and link it to categories.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::AddContentL()
+ {
+#ifdef _DEBUG
+
+ TBuf<KIptvEpgContentNameMaxLength + 1> name;
+ name.Zero();
+ if ( iContent )
+ {
+ name.Copy( iContent->iName );
+ }
+
+ IPTVLOGSTRING2_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::AddContentL: '%S'",
+ &name );
+#endif
+
+ TBool addThis( iContent && ( iMediaContentSet.Count() > 0 ) &&
+ iContent->iBrowserUrl.Length() < KIptvUrlMaxLength );
+ TInt itemCategories( iCurrentCategoryKeys.Count() );
+
+ // Check category limits.
+ if ( addThis )
+ {
+ addThis = EFalse;
+ if ( iContentCount < KIptvEpgMaxContentCount )
+ {
+ // Check whether this item fits to any selected category
+ for ( TInt key = 0;
+ ( key < itemCategories ) && ( EFalse == addThis );
+ key++ )
+ {
+ TUint32 categoryKey = iCurrentCategoryKeys[key];
+
+ if ( 0 < categoryKey )
+ {
+ if ( iCategoryTable[categoryKey - 1]->iContentCount <
+ KIptvEpgMaxContentCountInCategory )
+ {
+ addThis = ETrue;
+ }
+ }
+ }
+
+ if ( !addThis )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::AddContentL Content not added! Category limits reached!" );
+ }
+ }
+ else
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::AddContentL Content not added! Limit reached!" );
+ IPTVLOGSTRING3_LOW_LEVEL(
+ "RSS Plugin::AddContentL Total content count: %d/%d",
+ iContentCount,
+ KIptvEpgMaxContentCount );
+ }
+ }
+ else
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::AddContentL Content not added! Required info missing!" );
+ }
+
+ TUint32 newContentKey( 0 );
+
+ if ( addThis )
+ {
+ // Save content's thumbnail path
+ TBuf<KIptvCAContentUrlLength> thumbnailUrl;
+ thumbnailUrl.Copy( iContent->iIconFilePath );
+
+ // Set thumbnail path to zero, we dont want 2k URL's to database
+ iContent->iIconFilePath.Zero();
+
+ // Add order to content data.
+ // This is the item detection order and is not continuous
+ // inside one category. Anyway order is increasing inside each
+ // category and can so be used to sort items of category.
+ iContent->iOrder = iContentCount;
+
+ // Get size, duration and language from media content's
+ // full version to "parent" content class
+ // This becomes redundant information
+ TInt count = iMediaContentSet.Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ if ( iMediaContentSet[i]->iExpression ==
+ CIptvMediaContent::EFull )
+ {
+ iContent->iSize = iMediaContentSet[i]->iFileSize;
+ iContent->iDuration = iMediaContentSet[i]->iDuration;
+ iContent->iLanguage.Copy(
+ iMediaContentSet[i]->iLanguage );
+ i = count;
+ }
+ }
+
+ TInt error = iVodCallback->AddContentL(
+ *iContent, iMediaContentSet, newContentKey );
+ if ( error == KErrNone )
+ {
+ iContentCount++;
+ AddContentToDlQueueL( newContentKey, thumbnailUrl );
+
+ IPTVLOGSTRING3_LOW_LEVEL(
+ "RSS Plugin::AddContentL Content added, total content count: %d/%d",
+ iContentCount,
+ KIptvEpgMaxContentCount );
+ }
+ else
+ {
+ addThis = EFalse;
+ IPTVLOGSTRING2_LOW_LEVEL(
+ "RSS Plugin::AddContentL error = %d", error );
+ }
+ }
+
+ if ( addThis )
+ {
+ // Add relation to selected categories.
+ for ( TInt key = 0; key < itemCategories; key++ )
+ {
+ TUint32 categoryKey = iCurrentCategoryKeys[key];
+
+ if ( 0 < categoryKey )
+ {
+ if ( iCategoryTable[categoryKey - 1]->iContentCount <
+ KIptvEpgMaxContentCountInCategory )
+ {
+ iVodCallback->AddRelationL( categoryKey, newContentKey );
+ iCategoryTable[categoryKey - 1]->iContentCount++;
+
+ IPTVLOGSTRING3_LOW_LEVEL(
+ "RSS Plugin::AddContentL Content count in category: %d/%d",
+ iCategoryTable[categoryKey - 1]->iContentCount,
+ KIptvEpgMaxContentCountInCategory );
+ }
+ }
+ }
+ }
+ else
+ {
+ // After non added item, cleanup for empty categories.
+ // Because empty categories are checked after each rejected item,
+ // they can be assumed to be the last ones.
+ TInt categoryCount( iCategoryTable.Count() );
+
+ while ( 0 < categoryCount )
+ {
+ categoryCount--;
+ if ( 0 == iCategoryTable[categoryCount]->iContentCount )
+ {
+ if ( iCategoryTable[categoryCount] != iChannelCategory )
+ {
+#ifdef _DEBUG
+ name.Zero();
+ name.Copy( iCategoryTable[categoryCount]->iName );
+
+ IPTVLOGSTRING2_LOW_LEVEL(
+ "RSS Plugin::AddContentL Empty category '%S' removed ",
+ &name );
+#endif
+ delete iCategoryTable[categoryCount];
+ iCategoryTable[categoryCount] = NULL;
+ }
+ else
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::AddContentL Channel category unlinked" );
+ iChannelCategoryKey = 0;
+ iCategoryTable[categoryCount] = NULL;
+ }
+
+ iCategoryTable.Remove( categoryCount );
+ }
+ else
+ {
+ categoryCount = 0;
+ }
+ }
+ }
+
+ iMediaContents.ResetAndDestroy();
+ iMediaContentSet.Reset();
+ iCurrentCategoryKeys.Reset();
+
+ delete iContent;
+ iContent = NULL;
+ }
+
+// --------------------------------------------------------------------------
+// Create a new itme content descriptor.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::CreateContentL()
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::CreateContentL" );
+
+ delete iContent;
+ iContent = NULL;
+ iContent = CIptvEpgContent::NewL();
+
+ // Key is auto-increment
+
+ // Id
+ iContent->iId = KIptvEmptyDes;
+
+ // Name
+ iContent->iName = KIptvEmptyDes;
+
+ // Content protection
+ iContent->iContentProtection = 0;
+
+ // Icon file Id
+ iContent->iIconFileId = 0;
+
+ // Is icon filepath URL
+ iContent->iIsIconFilePathUrl = ETrue;
+
+ // Icon file path
+ iContent->iIconFilePath = KIptvEmptyDes;
+
+ // Content file Id
+ iContent->iContentFileId = 0;
+
+ // Content description
+ iContent->iDescription = KIptvEmptyDes;
+
+ // Author
+ iContent->iAuthor = KIptvEmptyDes;
+
+ // Copyright
+ iContent->iCopyright = KIptvEmptyDes;
+
+ // Size
+ iContent->iSize = 0;
+
+ // Duration
+ iContent->iDuration = 0;
+
+ // Language
+ iContent->iLanguage = KIptvEmptyDes;
+
+ // rating age by default unlimited.
+ iContent->iRatingAge = KRatingAgeUnlimited;
+ }
+
+// --------------------------------------------------------------------------
+// Adjust download type according to Mime type.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::SetDownloadTypeFromMimeType(
+ CIptvMediaContent& aContent ) const
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::SetDownloadTypeFromMimeType" );
+
+ // For some MIME types we force the download type.
+ //
+ if ( aContent.iMimeType.CompareF( KIptvMimeApplicationSdp ) == 0 )
+ {
+ aContent.iDownloadType = EIptvDownloadTypeStream;
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Item containing thumbnails is added to download queue.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::AddContentToDlQueueL(
+ TUint32 contentKey,
+ const TDesC& aThumbnailUrl )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::AddContentToDlQueueL" );
+
+ // If thumbnail path -> add to download queue
+ if ( ( aThumbnailUrl.Length() > 0 ) &&
+ ( aThumbnailUrl.Length() <= KIptvUrlMaxLength ) &&
+ ( aThumbnailUrl.Left( KIptvProtocolNameLength ).CompareF(
+ KIptvRssHttp ) == 0 ) )
+ {
+ CIptvDownloadItem* item = CIptvDownloadItem::NewL();
+ CleanupStack::PushL( item );
+ item->iThumbnailUrl.Copy( aThumbnailUrl );
+ item->iServiceThumbnail = EFalse;
+ item->iId = contentKey;
+ iPlugin.AddToDlQueueL( item );
+ CleanupStack::Pop( item );
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Service image thumbnails url is added to download queue.
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::AddServiceToDlQueueL(
+ const TDesC& aThumbnailUrl )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::AddServiceToDlQueueL" );
+
+ // Only first valid occurence is stored as service image.
+ if ( !iServiceThumbnailAdded )
+ {
+ TInt urlLength = aThumbnailUrl.Length();
+
+ // Url can not be truncated, if too long wait a new one.
+ // If thumbnail path -> add to download queue
+ if ( ( 0 < urlLength ) &&
+ ( KIptvEpgCategoryIconFilePathMaxLength >= urlLength ) &&
+ ( aThumbnailUrl.Left( KIptvProtocolNameLength ).CompareF(
+ KIptvRssHttp ) == 0 ) )
+ {
+ CIptvDownloadItem* item = CIptvDownloadItem::NewL();
+ CleanupStack::PushL( item );
+ item->iThumbnailUrl.Copy( aThumbnailUrl );
+ item->iServiceThumbnail = ETrue;
+ item->iId = iChannelCategoryKey;
+ iPlugin.AddToDlQueueL( item );
+ CleanupStack::Pop( item );
+
+ iServiceThumbnailAdded = ETrue;
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::AddServiceToDlQueueL Service thumbnail added" );
+ }
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CIptvXmlContentHandler::PriorizeL
+// --------------------------------------------------------------------------
+//
+void CIptvXmlContentHandler::PriorizeL()
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::PriorizeL" );
+
+ TInt count = iMediaContents.Count();
+ if ( count > 0 )
+ {
+ RPointerArray<CIptvMediaContent> previewStreams;
+ RPointerArray<CIptvMediaContent> previewDownloads;
+ RPointerArray<CIptvMediaContent> streams;
+ RPointerArray<CIptvMediaContent> downloads;
+
+ for ( TInt i = 0; i < count; i++ )
+ {
+ // Preview stream
+ //lint -e{961} Else block not needed, default is no operation.
+ if ( ( iMediaContents[i]->iExpression == CIptvMediaContent::ESample ) &&
+ ( iMediaContents[i]->iDownloadType == EIptvDownloadTypeStream ) )
+ {
+ previewStreams.AppendL( iMediaContents[i] );
+ }
+ // Preview download
+ else if ( ( iMediaContents[i]->iExpression == CIptvMediaContent::ESample ) &&
+ ( iMediaContents[i]->iDownloadType == EIptvDownloadTypeImmediate ) )
+ {
+ previewDownloads.AppendL( iMediaContents[i] );
+ }
+ // Stream ( full or nonstop )
+ else if ( ( iMediaContents[i]->iExpression != CIptvMediaContent::ESample ) &&
+ ( iMediaContents[i]->iDownloadType == EIptvDownloadTypeStream ) )
+ {
+ streams.AppendL( iMediaContents[i] );
+ }
+ // Download
+ else if ( ( iMediaContents[i]->iExpression == CIptvMediaContent::EFull ) &&
+ ( iMediaContents[i]->iDownloadType == EIptvDownloadTypeImmediate ) )
+ {
+ downloads.AppendL( iMediaContents[i] );
+ }
+ }
+
+ if ( iTerminalVideoSupport )
+ {
+ TInt index = 0;
+ if ( previewStreams.Count() > 0 )
+ {
+ index = iTerminalVideoSupport->SelectMimeTypeL( previewStreams );
+ if ( index != KErrNotFound )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::PriorizeL Best preview stream is:" );
+ previewStreams[index]->PrintL();
+
+ // Add best items of preview streams, preview downloads,
+ // streams and downloads to array
+ iMediaContentSet.AppendL( previewStreams[index] );
+ }
+ }
+ if ( previewDownloads.Count() > 0 )
+ {
+ index = iTerminalVideoSupport->SelectMimeTypeL( previewDownloads );
+ if ( index != KErrNotFound )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::PriorizeL Best preview download is:" );
+ previewDownloads[index]->PrintL();
+
+ iMediaContentSet.AppendL( previewDownloads[index] );
+ }
+ }
+ if ( streams.Count() > 0 )
+ {
+ index = iTerminalVideoSupport->SelectMimeTypeL( streams );
+ if ( index != KErrNotFound )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::PriorizeL Best stream is:" );
+ streams[index]->PrintL();
+
+ iMediaContentSet.AppendL( streams[index] );
+ }
+ }
+ if ( downloads.Count() > 0 )
+ {
+ index = iTerminalVideoSupport->SelectMimeTypeL( downloads );
+ if ( index != KErrNotFound )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::PriorizeL Best download is:" );
+ downloads[index]->PrintL();
+
+ iMediaContentSet.AppendL( downloads[ index ] );
+ }
+ }
+ }
+
+ previewStreams.Close();
+ previewDownloads.Close();
+ streams.Close();
+ downloads.Close();
+ }
+ }
+
+// --------------------------------------------------------------------------
+// Advances category state according to given event and decides whether
+// current object should be processed.
+// --------------------------------------------------------------------------
+//
+TBool CIptvXmlContentHandler::SetCategoryState( TCategoryStateEvent aEvent )
+ {
+ IPTVLOGSTRING3_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::SetCategoryState State:%d, Event:%d",
+ iCategoryState, aEvent );
+
+ TBool processThis( ETrue ); // By default we process this object
+
+ /**
+ * Search category attribute inside an item.
+ */
+ //lint -e{961} Else block not needed, default is no change.
+ if ( ECategoryFound == aEvent )
+ {
+ iCategoryFound = ETrue;
+ }
+ else if ( EItemFound == aEvent )
+ {
+ iCategoryFound = EFalse;
+ }
+
+ /**
+ * State transitions according to event.
+ */
+ switch ( iCategoryState )
+ {
+ /**
+ * Not even the first channel found yet.
+ */
+ case ENoChannel:
+ {
+ if ( EChannelFound == aEvent )
+ {
+ iCategoryState = EChannelNoItem;
+ }
+ }
+ break;
+
+ /**
+ * No items found from first channel yet.
+ */
+ case EChannelNoItem:
+ {
+ //lint -e{961} Else block not needed, default is no state change.
+ if ( EItemCompleted == aEvent )
+ {
+ if ( iCategoryFound )
+ {
+ iCategoryState = EItemsWithCategory;
+ iCategoryFound = EFalse;
+ }
+ else
+ {
+ iCategoryState = EItemsNoCategory;
+ }
+ }
+ else if ( EChannelCompleted == aEvent )
+ {
+ processThis = EFalse; // Ignore empty channel.
+ iCategoryState = ENoChannel;
+ }
+ }
+ break;
+
+ /**
+ * Only items with category definition found yet fron first channel.
+ */
+ case EItemsWithCategory:
+ {
+ //lint -e{961} Else block not needed, default is no state change.
+ if ( EItemCompleted == aEvent )
+ {
+ if ( iCategoryFound )
+ {
+ iCategoryFound = EFalse;
+ }
+ else
+ {
+ iCategoryState = EItemsBoth;
+ }
+ }
+ else if ( EChannelCompleted == aEvent )
+ {
+ iCategoryState = ESkipFurtherChannels;
+ processThis = EFalse; // Ignore channel name as category.
+ }
+ }
+ break;
+
+ /**
+ * Only items without category definition found yet fron first channel.
+ */
+ case EItemsNoCategory:
+ {
+ //lint -e{961} Else block not needed, default is no state change.
+ if ( EItemCompleted == aEvent )
+ {
+ if ( iCategoryFound )
+ {
+ iCategoryState = EItemsBoth;
+ iCategoryFound = EFalse;
+ }
+ }
+ else if ( EChannelCompleted == aEvent )
+ {
+ iCategoryState = ESkipFurtherCategories;
+ }
+ }
+ break;
+
+ /**
+ * First channel contains items both with and without categories.
+ */
+ case EItemsBoth:
+ {
+ if ( EChannelCompleted == aEvent )
+ {
+ iCategoryState = ESkipFurtherChannels;
+ }
+ }
+ break;
+
+ /**
+ * We have processed a channel with category definitions, so we are
+ * satisfied and ignore further channels.
+ */
+ case ESkipFurtherChannels:
+ {
+ if ( EChannelFound == aEvent )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::SetCategoryState ESkipFurtherChannels" );
+ processThis = EFalse;
+ }
+ }
+ break;
+
+ /**
+ * We have processed a channel without any category definitions,
+ * so we use channels as categories and ignore further category
+ * definitions.
+ */
+ case ESkipFurtherCategories:
+ {
+ if ( ECategoryFound == aEvent )
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::SetCategoryState SkipFurtherCategories" );
+ processThis = EFalse;
+ }
+ }
+ break;
+
+ default:
+ {
+ IPTVLOGSTRING_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::SetCategoryState Unknown state" );
+ }
+ }
+
+ IPTVLOGSTRING3_LOW_LEVEL(
+ "RSS Plugin::CIptvXmlContentHandler::SetCategoryState New State:%d, Process:%d",
+ iCategoryState, processThis );
+
+ return processThis;
+ }