upnpavcontroller/upnpxmlparser/src/upnpxmleventparser.cpp
author samhuttu
Mon, 01 Nov 2010 12:37:49 +0200
branchnew development branch with rendering state machine and other goodies
changeset 38 5360b7ddc251
parent 0 7f85d04be362
permissions -rw-r--r--
New development branch with e.g. rendering state machine and a simple Qt example application using it.

/*
* Copyright (c) 2006,2009 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:      XML SAX Parser for UPnP.
*
*/

#include <xml/parser.h>
#include <xml/parserfeature.h>
#include <upnpstring.h>
#include <xml/matchdata.h>

#include "upnpxmleventparser.h"
#include "upnpavtevent.h"

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

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

_LIT8( KEvent,          "Event"         );
_LIT8( KInstanceID,     "InstanceID"    );
_LIT8( KVolume,         "Volume"        );
_LIT8( KMute,           "Mute"          );
_LIT8( KDIDL,           "DIDL-Lite"     );
_LIT8( KDesc,           "desc"          );
_LIT8( KDlnaDoc,        "X_DLNADOC"     );
_LIT8( KVal,            "val"           );
_LIT8( KChannel,        "channel"       );
_LIT8( KMaster,         "Master"       );
_LIT8( KTransportState, "TransportState" );
_LIT8( KTransportURI,   "AVTransportURI" );

// --------------------------------------------------------------------------
// CUPnPXMLEventParser::CUPnPXMLEventParser()
// See upnpxmlparser.h
// --------------------------------------------------------------------------
CUPnPXMLEventParser::CUPnPXMLEventParser()
    {
    // No implementation required
    }

// --------------------------------------------------------------------------
// CUPnPXMLEventParser::ConstructL
// See upnpxmlparser.h
// --------------------------------------------------------------------------
void CUPnPXMLEventParser::ConstructL()
    {
    __LOG( "CUPnPXMLEventParser::CostructL" );
    
    iAvtEvent = CUPnPAVTEvent::NewL();
    iAvtResultEvent = CUPnPAVTEvent::NewL();
    }

// --------------------------------------------------------------------------
// CUPnPXMLEventParser::NewL
// See upnpxmlparser.h
// --------------------------------------------------------------------------
EXPORT_C CUPnPXMLEventParser* CUPnPXMLEventParser::NewL()
    {
    __LOG( "CUPnPXMLEventParser::NewL" );
    CUPnPXMLEventParser* self = new( ELeave ) CUPnPXMLEventParser();
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop(self);    
    return self;
    }
    
// --------------------------------------------------------------------------
// CUPnPXMLEventParser::~CUPnPXMLEventParser
// See upnpxmlparser.h
// --------------------------------------------------------------------------
CUPnPXMLEventParser::~CUPnPXMLEventParser()
    {
    __LOG( "CUPnPXMLEventParser::~CUPnPXMLEventParser" );
    
    delete iAvtEvent;
    delete iAvtResultEvent;
    }

// --------------------------------------------------------------------------
// CUPnPXMLEventParser::ParseRcEventDataL
// See upnpxmlparser.h
// --------------------------------------------------------------------------
EXPORT_C CUPnPAVTEvent* CUPnPXMLEventParser::ParseRcEventDataL(
    const TDesC8& aData, const TInt aInstanceId )
    {
    __LOG( "CUPnPXMLEventParser::ParseRcEventDataL, begin" );
    
    if ( !aData.Length() )
        {
        User::Leave( KErrArgument );
        }

    Reset();
    ResetResult();
    iSessionInstanceID = aInstanceId;
        
    // Create parser 
    CMatchData* matchData = CMatchData::NewLC();
    matchData->SetMimeTypeL( KXmlMimeType ); 
    matchData->SetVariantL( KLIB2XML ); 
    CParser* parser = CParser::NewLC( *matchData, *this ); 
    parser->EnableFeature( Xml::EReportNamespaceMapping );
    
    Xml::ParseL( *parser, aData );    
    
    CleanupStack::PopAndDestroy( parser );
    CleanupStack::PopAndDestroy( matchData );
    
    if( iAvtResultEvent->InstanceID() == KErrNotFound )
        {
        __LOG1( "CUPnPXMLEventParser::ParseRcEventDataL \
instanceid not matching %d",  iSessionInstanceID );
        User::Leave( KErrNotFound );
        }  
        
    return CUPnPAVTEvent::CloneL( *iAvtResultEvent );
    }


// --------------------------------------------------------------------------
// CUPnPXMLEventParser::ParseAVTEventDataL
// See upnpxmlparser.h
// --------------------------------------------------------------------------
EXPORT_C CUPnPAVTEvent* CUPnPXMLEventParser::ParseAvtEventDataL(
    const TDesC8& aData, const TInt aInstanceId )
    {
    __LOG( "CUPnPXMLEventParser::ParseAvtEventDataL, begin" );
    
    if ( !aData.Length() )
        {
        User::Leave( KErrArgument );
        }
    
    Reset();
    ResetResult();
    iSessionInstanceID = aInstanceId;
        
    // Create parser 
    CMatchData* matchData = CMatchData::NewLC();
    matchData->SetMimeTypeL( KXmlMimeType ); 
    matchData->SetVariantL( KLIB2XML ); 
    CParser* parser = CParser::NewLC( *matchData, *this ); 
    parser->EnableFeature( Xml::EReportNamespaceMapping );
    
    Xml::ParseL( *parser, aData );    
    
    CleanupStack::PopAndDestroy( parser );
    CleanupStack::PopAndDestroy( matchData );
    
    if( iAvtResultEvent->InstanceID() == KErrNotFound )
        {
        __LOG1( "CUPnPXMLEventParser::ParseAvtEventDataL \
instanceid not matching %d", iSessionInstanceID );
        User::Leave( KErrNotFound );
        }
    
    return CUPnPAVTEvent::CloneL( *iAvtResultEvent );
    }


// --------------------------------------------------------------------------
// CUPnPXMLEventParser::OnStartDocumentL
// See upnpxmlparser.h
// --------------------------------------------------------------------------
void CUPnPXMLEventParser::OnStartDocumentL( 
                                const RDocumentParameters& /*aDocParam*/, 
                                TInt /*aErrorCode*/ )
    {
    // No implementation needed
    }

// --------------------------------------------------------------------------
// CUPnPXMLEventParser::OnEndDocumentL
// See upnpxmlparser.h
// --------------------------------------------------------------------------
void CUPnPXMLEventParser::OnEndDocumentL( TInt /*aErrorCode*/ )
    {
    // No implementation needed
    }

// --------------------------------------------------------------------------
// CUPnPXMLEventParser::OnStartElementL
// See upnpxmlparser.h
// --------------------------------------------------------------------------
void CUPnPXMLEventParser::OnStartElementL( const RTagInfo& aElement, 
                                      const RAttributeArray& aAttributes,
                                      TInt aErrorCode )
    {   
    if ( aErrorCode != KErrNone )
        {
        __LOG1( "CUPnPXMLEventParser::OnStartElementL, error: %d",
                                                                aErrorCode );
        return;
        }
    const TDesC8& desName = aElement.LocalName().DesC();
    __LOG8_1("CUPnPXMLEventParser::OnStartElementL name = %S", &desName );
  
    if ( !desName.CompareF( KEvent ) )
        {
        iParserState = EEvent;
        }
    else if ( !desName.CompareF( KInstanceID ) )
        {
        iParserState = EInstanceID;
        SetAttributesL( aAttributes );
        }
    //Rc events
    else if( !desName.CompareF( KVolume ) )
        {
        iParserState = EVolume;
        SetAttributesL( aAttributes );
        }
    else if( !desName.CompareF( KMute ) )
        {
        iParserState = EMute;
        SetAttributesL( aAttributes );
        }  
    // Avt events 
    else if( !desName.CompareF( KTransportState ) )
        {
        iParserState = ETransportState;
        SetAttributesL( aAttributes );
        }
    else if ( !desName.CompareF( KTransportURI ) )
        {
        iParserState = ETransportURI;
        SetAttributesL( aAttributes );
        }
    
    // Ignore DIDL-Lite, desc and X_DLNADOC -elements (DLNA req)
    else if( desName.Compare( KDIDL ) == KErrNone ||
             desName.Compare( KDesc ) == KErrNone ||
             desName.Compare( KDlnaDoc ) == KErrNone    
           )
        {
        // Ignore
        }
    else 
        {
        // just print attribute values
        iParserState = ENotSupported;
        SetAttributesL( aAttributes );
        }
    }

// --------------------------------------------------------------------------
// CUPnPXMLEventParser::OnEndElementL
// See upnpxmlparser.h
// --------------------------------------------------------------------------
void CUPnPXMLEventParser::OnEndElementL( const RTagInfo& aElement, 
                                    TInt /*aErrorCode*/ )
    {
    // if we have finished parsing one event,
    // check that it belongs to our session
    const TDesC8& desName = aElement.LocalName().DesC();
    
    if ( !desName.CompareF( KInstanceID ) )
        {
        if( iAvtEvent->InstanceID() == iSessionInstanceID )
            {
            iAvtResultEvent->Reset();
            iAvtResultEvent->SetInstanceID( iAvtEvent->InstanceID() );
            iAvtResultEvent->SetMute( iAvtEvent->Mute() );
            iAvtResultEvent->SetVolume( iAvtEvent->Volume() );
            iAvtResultEvent->SetTransportState( iAvtEvent->TransportState() );
            iAvtResultEvent->SetTransportURIL( iAvtEvent->TransportURI() );
            
            __LOG( "CUPnPXMLEventParser::OnEndElementL() valid event" );
            }
        else
            {
            __LOG2( "CUPnPXMLEventParser OnEndElementL ERROR instanceid not \
matching session %d, event %d", iSessionInstanceID, iAvtEvent->InstanceID());
            }
            
        Reset();
        }
    }

// --------------------------------------------------------------------------
// CUPnPXMLEventParser::OnContentL
// See upnpxmlparser.h
// --------------------------------------------------------------------------
void CUPnPXMLEventParser::OnContentL( const TDesC8& /*aBytes*/,
    TInt /*aErrorCode*/ )
    {
    // No implementation needed
    }

// --------------------------------------------------------------------------
// CUPnPXMLEventParser::OnStartPrefixMappingL
// See upnpxmlparser.h
// --------------------------------------------------------------------------
void CUPnPXMLEventParser::OnStartPrefixMappingL( const RString& /*aPrefix*/, 
                                               const RString& /*aUri*/, 
                                               TInt /*aErrorCode*/ )
    {
    // No implementation needed
    }

// --------------------------------------------------------------------------
// CUPnPXMLEventParser::OnEndPrefixMappingL
// See upnpxmlparser.h
// --------------------------------------------------------------------------
void CUPnPXMLEventParser::OnEndPrefixMappingL( const RString& /*aPrefix*/, 
                                             TInt /*aErrorCode*/ )
    {
    // No implementation needed
    }

// --------------------------------------------------------------------------
// CUPnPXMLEventParser::OnIgnorableWhiteSpaceL
// See upnpxmlparser.h
// --------------------------------------------------------------------------
void CUPnPXMLEventParser::OnIgnorableWhiteSpaceL( const TDesC8& /*aBytes*/, 
                                                TInt /*aErrorCode*/ )
    {
    // No implementation needed
    }

// --------------------------------------------------------------------------
// CUPnPXMLEventParser::OnSkippedEntityL
// See upnpxmlparser.h
// --------------------------------------------------------------------------
void CUPnPXMLEventParser::OnSkippedEntityL( const RString& /*aName*/, 
                                          TInt /*aErrorCode*/ )
    {
    // No implementation needed
    }

// --------------------------------------------------------------------------
// CUPnPXMLEventParser::OnProcessingInstructionL
// See upnpxmlparser.h
// --------------------------------------------------------------------------
void CUPnPXMLEventParser::OnProcessingInstructionL(
    const TDesC8& /*aTarget*/, const TDesC8& /*aData*/, TInt /*aErrorCode*/ )
    {
    // No implementation needed
    }

// --------------------------------------------------------------------------
// CUPnPXMLEventParser::OnError
// See upnpxmlparser.h
// --------------------------------------------------------------------------
void CUPnPXMLEventParser::OnError( TInt /*aErrorCode*/ )
    {
    // No implementation needed
    }

// --------------------------------------------------------------------------
// CUPnPXMLEventParser::GetExtendedInterface
// See upnpxmlparser.h
// --------------------------------------------------------------------------
TAny* CUPnPXMLEventParser::GetExtendedInterface( const TInt32 /*aUid*/ )
    {    
    // No implementation needed
    return NULL;
    }

// --------------------------------------------------------------------------
// CUPnPXMLEventParser::SetAttributesL
// See upnpxmlparser.h
// --------------------------------------------------------------------------
void CUPnPXMLEventParser::SetAttributesL(
    const RAttributeArray& aAttributes )
    {
    RAttribute attribute;
    TInt count = aAttributes.Count();
    TInt volume = KErrNotFound;
    iMasterVolumeState = EFalse;
    
    for ( TInt i = 0; i < count ; i++ )
        {
        attribute = aAttributes[i];
        const TDesC8& name = attribute.Attribute().LocalName().DesC();
        const TDesC8& value = attribute.Value().DesC();
        if( value.Length() )
            {
            __LOG8_1( "CUPnPXMLEventParser::SetAttributesL value = %S",
                    &value );
            }
        
        // volume & channel
        if ( iParserState == EVolume )
            {
            // assign the value of Volume to volume 
            if ( name.CompareF( KVal ) == KErrNone )
                {
                TLex8 lexer( value );
                User::LeaveIfError( lexer.Val(volume) );
                }
            else if ( name.CompareF( KChannel ) == KErrNone )
                {
                // channel is found, check if is Master
                if ( value.CompareF( KMaster ) == KErrNone )
                    {
                    __LOG( "CUPnPXMLEventParser::SetAttributesL - \
MasterVolume found!" );
                    iMasterVolumeState = ETrue;
                    }
                }
            }
          
          
                     
              
        // other values
        else if ( name.Compare( KVal ) == KErrNone )
            {
            TLex8 lexer( value );
            
            if ( iParserState == EInstanceID )
                {
                TInt id = KErrNotFound;
                User::LeaveIfError( lexer.Val( id ) );
                iAvtEvent->SetInstanceID( id );
                }
            else if ( iParserState == EMute )
                {
                TInt mute = KErrNotFound;
                User::LeaveIfError( lexer.Val( mute ) );
                iAvtEvent->SetMute( mute );
                }
            else if ( iParserState == ETransportState )
                {
                iAvtEvent->SetTransportState( value );
                }
            else if ( iParserState == ETransportURI )
                {
                iAvtEvent->SetTransportURIL( value );
                }
            else
                {
                __LOG( "CUPnPXMLEventParser::SetAttributesL - \
unknown state" );
                }
            }
        }
    
    // check Mastervolume and volume
    if ( iParserState == EVolume && 
         iMasterVolumeState && 
         volume != KErrNotFound )
        {
        // all is found ,so assign the iVolume
        __LOG1( "CUPnPXMLEventParser::SetAttributesL - set iVolume : %d",
                                                                     volume );
        iAvtEvent->SetVolume( volume );       
        }
    }
    
// --------------------------------------------------------------------------
// CUPnPXMLEventParser::Reset
// See upnpxmlparser.h
// --------------------------------------------------------------------------
void CUPnPXMLEventParser::Reset()
    {
    iParserState = ENotSupported;
    iMasterVolumeState = EFalse;
    
    iAvtEvent->Reset();
    }

// --------------------------------------------------------------------------
// CUPnPXMLEventParser::ResetResult
// See upnpxmlparser.h
// --------------------------------------------------------------------------
void CUPnPXMLEventParser::ResetResult()
    {
    iSessionInstanceID = KErrNotFound;
    iParserState = ENotSupported;
    iMasterVolumeState = EFalse;
    
    iAvtResultEvent->Reset();
    }     
         
// end of file