diff -r 000000000000 -r 96612d01cf9f videofeeds/mrssplugin/src/CIptv3XmlContentHandler.cpp --- /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 +#include "MIptvEpgVodCallback.h" +#include "CIptvEpgCategory.h" +#include "CIptvEpgContent.h" +#include "IptvDebug.h" +#include +#include +#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 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 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 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 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 previewStreams; + RPointerArray previewDownloads; + RPointerArray streams; + RPointerArray 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; + }