upnpsharing/upnpgstwrapper/src/upnprenderercfgparser.cpp
author Sampo Huttunen <sampo.huttunen@nokia.com>
Wed, 03 Nov 2010 11:45:09 +0200
branchIOP_Improvements
changeset 40 08b5eae9f9ff
permissions -rw-r--r--
merge from Nokia's internal development branch

/*
* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:  Implementation of UPnP GStreamer wrapper
*
*/

// INCLUDES
#include <xml/parser.h>
#include <xml/parserfeature.h>
#include <xml/matchdata.h>
#include <xml/xmlparsererrors.h>
#include <f32file.h>
#include <s32file.h>
#include <upnpaction.h>
#include <upnpstring.h>

#include "upnprenderercfg.h"
#include "upnprenderercfgparser.h"

_LIT( KComponentLogfile, "upnprenderercfgparser.txt");
#include "upnplog.h"

#define __FUNC_LOG __LOG8_1( "%s", __PRETTY_FUNCTION__ );

//tags
_LIT8( KTranscoding,             "transcoding" );
_LIT8( KPipeline,                "pipeline" );
_LIT8( KProtocolInfo,            "protocolInfo" );
_LIT8( KSizeMultiplier,          "sizeMultiplier" );
_LIT8( KRenderer,                "renderer" );
_LIT8( KConfig,                  "config" );

//attributes
_LIT8( KExactMatch,              "exactMatch" );
_LIT8( KModelName,               "modelName" );
_LIT8( KSrcMimeType,             "srcMimeType" );

_LIT8( KFalse,                    "0" );

_LIT8( KXmlMimeType,             "text/xml" );
_LIT8( KLIB2XML,                 "libxml2" );

const TUint8 KCharSpace = 32; // Space
const TUint8 KCharDel = 127;  // DEL

using namespace Xml;

// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::NewL()
// (See comments in header file)
// --------------------------------------------------------------------------
//
EXPORT_C CUpnpRendererCfgParser* CUpnpRendererCfgParser::NewL()
    {
    __FUNC_LOG;
    
    CUpnpRendererCfgParser* self = CUpnpRendererCfgParser::NewLC();
    CleanupStack::Pop( self );    
    return self;
    }    

// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::NewLC()
// (See comments in header file)
// --------------------------------------------------------------------------
//
EXPORT_C CUpnpRendererCfgParser* CUpnpRendererCfgParser::NewLC()
    {
    __FUNC_LOG;
    
    CUpnpRendererCfgParser* self = new( ELeave ) CUpnpRendererCfgParser();
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;    
    }

// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::~CUpnpRendererCfgParser()
// (See comments in header file)
// --------------------------------------------------------------------------
//
EXPORT_C CUpnpRendererCfgParser::~CUpnpRendererCfgParser()
    {   
    __FUNC_LOG; 
    
    delete iParser;
    delete iMatchData;
    
    iFs.Close();
    }
    
// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::CUpnpRendererCfgParser()
// (See comments in header file)
// --------------------------------------------------------------------------
//
CUpnpRendererCfgParser::CUpnpRendererCfgParser()
    : iSizeMultiplier( KErrNotFound )
    {
    __FUNC_LOG;
    // No implementation needed    
    }

// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::ConstructL()
// (See comments in header file)
// --------------------------------------------------------------------------
//    
void CUpnpRendererCfgParser::ConstructL()
    {
    __FUNC_LOG;
    
    iMatchData = CMatchData::NewL();
    iMatchData->SetMimeTypeL( KXmlMimeType ); 
    iMatchData->SetVariantL( KLIB2XML ); 
    iParser = CParser::NewL( *iMatchData, *this );    
    iParser->EnableFeature( ESendFullContentInOneChunk );
    
    User::LeaveIfError( iFs.Connect() );
    }

// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::ParseRendererCfgL()
// (See comments in header file)
// --------------------------------------------------------------------------
//
EXPORT_C void CUpnpRendererCfgParser::ParseRendererCfgL( 
        CUpnpRendererCfg& aRendereConfig )
    {     
    __FUNC_LOG;             
    
    if( aRendereConfig.iPipeline || 
        aRendereConfig.iProtocolInfo || 
        aRendereConfig.iSizeMultiplier != KErrNotFound )
        {
        //these values should be still untouched
        User::Leave( KErrArgument );
        }
    
    iModelName = aRendereConfig.iModelName;
    iSrcMimeType = aRendereConfig.iSrcMimeType;
    
    //syncronous call -> returns when the file is fully parsed
    XMLParseL( *aRendereConfig.iConfigFile );

    if( !iPipeline || !iProtocolInfo || iSizeMultiplier == KErrNotFound )
        {
        __LOG8_1( "Couldn't find all the config elements for %S", 
                iModelName );
        
        //delete allocated bufs and reset vars
        delete iPipeline; iPipeline = NULL;        
        delete iProtocolInfo; iProtocolInfo = NULL;                
        
        //make sure that everything is in init state
        Reset();
        
        User::Leave( KErrNotFound );
        }
            
    aRendereConfig.iPipeline = iPipeline; //ownership transfer 
    aRendereConfig.iProtocolInfo = iProtocolInfo; //ownership transfer    
    aRendereConfig.iSizeMultiplier = iSizeMultiplier;    
    
    //make sure that everything is in init state
    Reset();
    }

// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::XMLParseL()
// (See comments in header file)
// --------------------------------------------------------------------------
//
void CUpnpRendererCfgParser::XMLParseL( const TDesC& aFile )
    {
    __FUNC_LOG;
   
    RFile file;
    User::LeaveIfError( file.Open( iFs, aFile , EFileRead ) );
    CleanupClosePushL( file );
    
    TInt size;
    User::LeaveIfError( file.Size( size ) );
    
    HBufC8* buf = HBufC8::NewLC( size );
    TPtr8 ptr = buf->Des();
    User::LeaveIfError( file.Read( ptr ) );
    
    Xml::ParseL( *iParser, *buf );
    
    CleanupStack::PopAndDestroy( buf );
    CleanupStack::PopAndDestroy( &file );    
    }

// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::Reset()
// (See comments in header file)
// --------------------------------------------------------------------------
//
void CUpnpRendererCfgParser::Reset()
    {
    __FUNC_LOG;
        
    iCurrentElement = EUnknown;
    iCorrectModel = EFalse;
    iCorrectTranscoding = EFalse;
    iModelName = NULL;
    iSrcMimeType = NULL;
    iPipeline = NULL;
    iProtocolInfo = NULL;
    iSizeMultiplier = KErrNotFound;
    }
    
// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::Element()
// (See comments in header file)
// --------------------------------------------------------------------------
//
CUpnpRendererCfgParser::TCfgElements CUpnpRendererCfgParser::Element(  
        const RTagInfo& aElement )
    {
    __FUNC_LOG;
    
    TCfgElements element = EUnknown;
    
    const TDesC8& desName = aElement.LocalName().DesC();   
    
    if( desName.CompareF( KTranscoding ) == 0 )
        {
        element = ETranscoding;
        }
    else if( desName.CompareF( KPipeline ) == 0 )
        {
        element = EPipeline;
        }
    else if( desName.CompareF( KProtocolInfo ) == 0 )
        {
        element = EProtocolInfo;
        }
    else if( desName.CompareF( KSizeMultiplier ) == 0 )
        {
        element = ESizeMultiplier;
        }
    else if( desName.CompareF( KRenderer ) == 0 )
        {
        element = ERenderer;
        }
    else if( desName.CompareF( KConfig ) == 0 )
        {
        element = EConfig;
        }
    else
       {
       __LOG8_1( "Error: Unknown element %S", &desName );
       __ASSERT( EFalse, __FILE__, __LINE__ );
       }
       
    return element;
    }
    
// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::ContainsAttribute()
// (See comments in header file)
// --------------------------------------------------------------------------
//
TBool CUpnpRendererCfgParser::ContainsAttribute( 
        const RAttributeArray& aAttributes, const TDesC8& aAttributeName, 
        const TDesC8& aAttributeValue, TBool aExactValueMatch )
    {
    __FUNC_LOG;
      
    TInt attributeCount = aAttributes.Count();
    for( TInt i = 0; i < attributeCount; i++ )
        {
        Xml::RAttribute attr = aAttributes[i];                      

        if( attr.Attribute().LocalName().DesC() == aAttributeName )
            {
            if( aExactValueMatch )
                {
                if( aAttributeValue.CompareF( attr.Value().DesC() ) == 0 )
                    {
                    //requested exact value match found
                    return ETrue;
                    }
                }
            else if( aAttributeValue.FindF( attr.Value().DesC() ) >= 0 )
                {
                //requested non-exact value match (sub-string) found
                return ETrue;
                }
            }
        }
        
    return EFalse;
    }

// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::OnStartDocumentL()
// (See comments in header file)
// --------------------------------------------------------------------------
//
void CUpnpRendererCfgParser::OnStartDocumentL( 
        const RDocumentParameters& /*aDocParam*/,
        TInt /*aErrorCode*/ )
    {    
    __FUNC_LOG;
    
    // No implementation needed
    }    

// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::OnEndDocumentL()
// (See comments in header file)
// --------------------------------------------------------------------------
//
void CUpnpRendererCfgParser::OnEndDocumentL( TInt /*aErrorCode*/ )
    {
    __FUNC_LOG;
    
    // No implementation needed
    }   

// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::OnStartElementL()
// (See comments in header file)
// --------------------------------------------------------------------------
//
void CUpnpRendererCfgParser::OnStartElementL( const RTagInfo& aElement,
        const RAttributeArray& aAttributes, TInt aErrorCode )
    {    
    __FUNC_LOG;
    __ASSERT( !aErrorCode, __FILE__, __LINE__ );
        
    iCurrentElement = Element( aElement );
    
    switch( iCurrentElement )
        {
        case EConfig:         //fall through
        case EPipeline:       //fall through
        case EProtocolInfo:   //fall through
        case ESizeMultiplier:
            {
            break;
            }
        case ERenderer:
            {      
            TBool exactMatch = ETrue;
            if( ContainsAttribute( aAttributes, KExactMatch, KFalse, 
                    ETrue ) )
                {
                exactMatch = EFalse;
                }
                    
            if( ContainsAttribute( aAttributes, KModelName, *iModelName, 
                    exactMatch ) )
                {
                iCorrectModel = ETrue;
                }
            else
                {
                iCorrectModel = EFalse;
                } 
            break;
            }
        case ETranscoding:
            {
            if( iCorrectModel &&
                ContainsAttribute( aAttributes, KSrcMimeType, *iSrcMimeType,
                    ETrue ) )
                {
                // correct transcoding found 
                // -> assert if something is already set
                __ASSERT( !iPipeline, __FILE__, __LINE__ );        
                __ASSERT( !iProtocolInfo, __FILE__, __LINE__ );     
                __ASSERT( iSizeMultiplier == KErrNotFound, __FILE__, 
                        __LINE__ );     
                                            
                iCorrectTranscoding = ETrue;
                }
            break;
            }
        default:
            {
            __ASSERT( EFalse, __FILE__, __LINE__ );
            }
        }  
    }

// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::OnEndElementL()
// (See comments in header file)
// --------------------------------------------------------------------------
//
void CUpnpRendererCfgParser::OnEndElementL( const RTagInfo& aElement, 
        TInt /*aErrorCode*/ )
    {
    __FUNC_LOG;
    
    if( iCurrentElement == EUnknown )
        {
        //at least second OnEndElementL callback in a row -> fetch enum
        iCurrentElement = Element( aElement );
        }
    
    switch( iCurrentElement )
        {
        case EPipeline:     //fall through
        case EProtocolInfo: //fall through
        case ESizeMultiplier:      
            {
            break;
            }
        case EUnknown:      //fall through
        case EConfig:       //fall through
        case ERenderer:
            {
            iCorrectModel = EFalse;
            //fall through
            }
        case ETranscoding:
            {
            iCorrectTranscoding = EFalse;
            break;
            }
        default:
            {
            __ASSERT( EFalse, __FILE__, __LINE__ );
            }            
        }    
        
    //exiting from element -> reset current element
    iCurrentElement = EUnknown;
    }

// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::OnContentL()
// (See comments in header file)
// --------------------------------------------------------------------------
//
void CUpnpRendererCfgParser::OnContentL( const TDesC8& aBytes, 
        TInt aErrorCode )
    {
    __FUNC_LOG;
    __ASSERT( !aErrorCode, __FILE__, __LINE__ );
    
    TUint8 firstChar = aBytes[0];    
    if( firstChar <= KCharSpace || firstChar == KCharDel )
        {
        //1st char of the content is a special char -> skip
        return;
        }
    
    switch( iCurrentElement )
        {
        case EConfig:   //fall through
        case ERenderer: //fall through
        case ETranscoding:
            break;
        case EPipeline:
            {
            if( iCorrectTranscoding )
                {
                //shouldn't contain any parsed value yet
                __ASSERT( !iPipeline, __FILE__, __LINE__ );
                       
                iPipeline = HBufC8::NewL( aBytes.Length() );
                iPipeline->Des().Copy( aBytes ); 
                }
            break;
            }
        case EProtocolInfo:
            {
            if( iCorrectTranscoding )
                {
                //shouldn't contain any parsed value yet
                __ASSERT( !iProtocolInfo, __FILE__, __LINE__ );
                
                iProtocolInfo = HBufC8::NewL( aBytes.Length() );
                iProtocolInfo->Des().Copy( aBytes ); 
                }
            break;
            }
        case ESizeMultiplier:
            {
            if( iCorrectTranscoding )
                {
                //shouldn't contain any parsed value yet
                __ASSERT( iSizeMultiplier == KErrNotFound, __FILE__, 
                        __LINE__ );
                
                TLex8 lex;
                lex.Assign( aBytes );                
                TInt err = lex.Val( iSizeMultiplier );
                
                __ASSERT( !err, __FILE__, __LINE__ );
                }
            break;
            }
        default:
            {
            __ASSERT( EFalse, __FILE__, __LINE__ );
            }            
        }
    }

// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::OnStartPrefixMappingL()
// (See comments in header file)
// --------------------------------------------------------------------------
//
void CUpnpRendererCfgParser::OnStartPrefixMappingL( 
        const RString& /*aPrefix*/, const RString& /*aUri*/, 
        TInt /*aErrorCode*/ )
    {
    __FUNC_LOG;
    
    // No implementation needed
    }
// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::OnEndPrefixMappingL()
// (See comments in header file)
// --------------------------------------------------------------------------
//
void CUpnpRendererCfgParser::OnEndPrefixMappingL( const RString& /*aPrefix*/,
        TInt /*aErrorCode*/ )
    {
    __FUNC_LOG;
    
    // No implementation needed
    }

// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::OnIgnorableWhiteSpaceL()
// (See comments in header file)
// --------------------------------------------------------------------------
//
void CUpnpRendererCfgParser::OnIgnorableWhiteSpaceL( const TDesC8& /*aBytes*/, 
        TInt /*aErrorCode*/ )
    {
    __FUNC_LOG;
    
    // No implementation needed
    }

// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::OnSkippedEntityL()
// (See comments in header file)
// --------------------------------------------------------------------------
//
void CUpnpRendererCfgParser::OnSkippedEntityL( const RString& /*aName*/, 
        TInt /*aErrorCode*/ )
    {
    __FUNC_LOG;
    
    // No implementation needed
    }

// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::OnProcessingInstructionL()
// (See comments in header file)
// --------------------------------------------------------------------------
//
void CUpnpRendererCfgParser::OnProcessingInstructionL( 
        const TDesC8& /*aTarget*/, 
        const TDesC8& /*aData*/,
        TInt /*aErrorCode*/ )
    {
    __FUNC_LOG;
    
    // No implementation needed
    } 

// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::OnError()
// (See comments in header file)
// --------------------------------------------------------------------------
//
void CUpnpRendererCfgParser::OnError( TInt /*aErrorCode*/ )
    {
    __FUNC_LOG;
    
    // No implementation needed
    }  

// --------------------------------------------------------------------------
// CUpnpRendererCfgParser::GetExtendedInterface()
// (See comments in header file)
// --------------------------------------------------------------------------
//
TAny* CUpnpRendererCfgParser::GetExtendedInterface( const TInt32 /*aUid*/ )
    {
    __FUNC_LOG;
    
    // No implementation needed
    return NULL;
    }


// end of file