diff -r 000000000000 -r 1bce908db942 multimediacommscontroller/mmcccontroller/src/mccresourceitem.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/multimediacommscontroller/mmcccontroller/src/mccresourceitem.cpp Tue Feb 02 01:04:58 2010 +0200 @@ -0,0 +1,817 @@ +/* +* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + + +// INCLUDE FILES +#include "mccresourceitem.h" +#include "mccuids.hrh" +#include "mcccontrollerlogs.h" +#include "mccmultiplexer.h" +#include "mccinternaldef.h" +#include "mcccamerahandler.h" + +#include +#include + +// EXTERNAL DATA STRUCTURES + +// EXTERNAL FUNCTION PROTOTYPES + +// CONSTANTS +const TInt KMccOneResourceUser = 1; + +// MACROS + +// LOCAL CONSTANTS AND MACROS + +// MODULE DATA STRUCTURES + +// LOCAL FUNCTION PROTOTYPES + +// FORWARD DECLARATIONS + +// ============================= LOCAL FUNCTIONS =============================== + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CMccResourceItem::NewLC +// ----------------------------------------------------------------------------- +// +CMccResourceItem* CMccResourceItem::NewLC( + TUint32 aCurrentUserStreamId, + MDataSink* aSink, + MDataSource* aSource, + TUint32 aEndpointId, + TBool aIsMultiplexer ) + { + CMccResourceItem* self = + new ( ELeave ) CMccResourceItem( aCurrentUserStreamId, + aEndpointId, + aIsMultiplexer ); + CleanupStack::PushL( self ); + self->ConstructL( aSink, aSource ); + return self; + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::NewL +// ----------------------------------------------------------------------------- +// +CMccResourceItem* CMccResourceItem::NewL( + TUint32 aCurrentUserStreamId, + MDataSink* aSink, + MDataSource* aSource, + TUint32 aEndpointId, + TBool aIsMultiplexer ) + { + CMccResourceItem* self = + CMccResourceItem::NewLC( aCurrentUserStreamId, + aSink, + aSource, + aEndpointId, + aIsMultiplexer ); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::~CMccResourceItem +// ----------------------------------------------------------------------------- +// +CMccResourceItem::~CMccResourceItem() + { + __CONTROLLER( "CMccResourceItem::~CMccResourceItem" ) + + delete iMultiplexerItem; + delete iMultiplexer; + iUsers.Reset(); + iUsers.Close(); + + iKeyFrameInfo.Close(); + + __CONTROLLER( "CMccResourceItem::~CMccResourceItem, exit" ) + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::IncreaseRefCount +// ----------------------------------------------------------------------------- +// +TInt CMccResourceItem::IncreaseRefCount( const TMccResourceParams& aUser ) + { + __CONTROLLER( "CMccResourceItem::IncreaseRefCount" ) + + TInt err = iUsers.Append( aUser ); + if ( !err && iMultiplexerItem ) + { + __CONTROLLER( "CMccResourceItem::IncreaseRefCount, call multiplexer" ) + + // Inform also the multiplexer + err = iMultiplexerItem->IncreaseRefCount( aUser ); + } + return err; + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::DecreaseRefCount +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::DecreaseRefCount( const TMccResourceParams& aUser ) + { + __CONTROLLER( "CMccResourceItem::DecreaseRefCount" ) + + TIdentityRelation comparison( UserMatch ); + TInt index = iUsers.Find( aUser, comparison ); + if ( index != KErrNotFound ) + { + iUsers.Remove( index ); + + // Inform also the multiplexer + if ( iMultiplexerItem ) + { + __CONTROLLER( "CMccResourceItem::DecreaseRefCount, call multiplexer" ) + + if ( iMultiplexerItem->DecreaseRefCount( aUser ) ) + { + __CONTROLLER( "CMccResourceItem::DecreaseRefCount, delete multiplexer" ) + + delete iMultiplexerItem; + iMultiplexerItem = 0; + } + } + } + // If no more users, resource item can be deleted + if ( iUsers.Count() == 0 ) + { + __CONTROLLER( "CMccResourceItem::DecreaseRefCount, can be removed" ) + + return ETrue; + } + + __CONTROLLER( "CMccResourceItem::DecreaseRefCount, cannot be removed" ) + + iCurrentUserStreamId = iUsers[ 0 ].iStreamId; + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::RefCount +// ----------------------------------------------------------------------------- +// +TInt CMccResourceItem::RefCount() const + { + return iUsers.Count(); + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::EndpointId +// ----------------------------------------------------------------------------- +// +TUint32 CMccResourceItem::EndpointId() const + { + return iEndpointId; + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::IsNetworkResource +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::IsNetworkResource() const + { + TBool isNetworkResource = iSink ? + iSink->DataSinkType().iUid == KImplUidRtpDataSink : + iSource->DataSourceType().iUid == KImplUidRtpDataSource; + + return isNetworkResource; + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::IsResourceActive +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::IsResourceActive() const + { + return ( iState == MMccResources::EPrepared || + iState == MMccResources::EStarted ); + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::IsSharedResource +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::IsSharedResource() const + { + TBool sharable = iIsMultiplexer || ( RefCount() > KMccOneResourceUser ); + + return sharable; + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::IsStandbyResource +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::IsStandbyResource() const + { + TBool standby( EFalse ); + if ( iSink && iSink->DataSinkType() == KUidMmfAudioOutput ) + { + for ( TInt i = 0; i < iUsers.Count() && !standby; i++ ) + { + standby = iUsers[ i ].iIsStandby; + } + } + return standby; + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::NeedsCamera +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::NeedsCamera( CMccCameraHandler& aCameraHandler ) + { + TBool needsCamera( EFalse ); + if ( iState == MMccResources::EStarted ) + { + needsCamera = ETrue; + } + else if ( iState == MMccResources::EPrepared ) + { + needsCamera = aCameraHandler.IsViewFinderEnabled(); + } + else + { + // NOP + } + return needsCamera; + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::SetResourceStateL +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::SetResourceStateL( + TUint32 aStreamId, + MMccResources::TResourceState aState, + TBool aStandbyControl, + TBool aDtmfControl ) + { + __CONTROLLER_INT1( "CMccResourceItem::SetResourceStateL, old state:", iState ) + __CONTROLLER_INT1( "CMccResourceItem::SetResourceStateL, proposed state:", aState ) + + TBool effectiveStateChange = EFalse; + + if ( iMultiplexerItem ) + { + __CONTROLLER( "CMccResourceItem::SetResourceStateL, multiplexer decision" ) + + effectiveStateChange = + iMultiplexerItem->SetResourceStateL( + aStreamId, aState, aStandbyControl, aDtmfControl ); + + // Actual resource follows multiplexer states + iState = iMultiplexerItem->CurrentState(); + } + else + { + __CONTROLLER( "CMccResourceItem::SetResourceStateL, resource usage allowed" ) + + // For shared resources, all resource state change operations should + // be passed further. + effectiveStateChange = IsSharedResource(); + + TBool isStandbyResource = IsStandbyResource(); + + if ( isStandbyResource || aDtmfControl ) + { + // Special handling for standby resource and dtmf + SpecialStateChangeL( aStreamId, + aState, + aStandbyControl, + aDtmfControl, + effectiveStateChange ); + } + else + { + TBool stateOK( EFalse ); + + switch ( aState ) + { + case MMccResources::EPrepared: + { + if ( MMccResources::EConstructed == iState ) + { + stateOK = ETrue; + } + else if ( iState == MMccResources::EStarted || + iState == MMccResources::EResourcePaused ) + { + // Endpoint is already started by other user, + // state is not "downgraded" + aState = iState; + stateOK = ETrue; + } + else + { + // NOP + } + break; + } + case MMccResources::EStarted: + { + if ( MMccResources::EPrepared == iState || + MMccResources::EResourcePaused == iState ) + { + stateOK = ETrue; + } + break; + } + case MMccResources::EResourcePaused: + { + if ( MMccResources::EStarted == iState ) + { + stateOK = ETrue; + } + break; + } + case MMccResources::EResourceStopped: + { + // Endpoint cannot be stopped until all its users + // want to stop it. + if ( !UserStopL( aStreamId ) ) + { + aState = iState; + effectiveStateChange = EFalse; + } + stateOK = ETrue; + break; + } + default: + { + break; + } + } + + if ( aState != iState ) + { + __ASSERT_ALWAYS( stateOK || effectiveStateChange, + User::Leave( KErrNotReady ) ); + + iState = aState; + + effectiveStateChange = ETrue; + } + } + } + + __CONTROLLER_INT1( "CMccResourceItem::SetResourceStateL, effective change:", + effectiveStateChange ) + __CONTROLLER_INT1( "CMccResourceItem::SetResourceStateL, exit with state:", + iState ) + + return effectiveStateChange; + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::IsSink +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::IsSink() const + { + return ( iSink != 0 ); + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::IsSource +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::IsSource() const + { + return ( iSource != 0 ); + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::IsInternal +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::IsInternal() const + { + TBool isInternal = iSink ? IsInternal( iSink->DataSinkType().iUid ) : + IsInternal( iSource->DataSourceType().iUid ); + + return isInternal; + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::Source +// ----------------------------------------------------------------------------- +// +MDataSource* CMccResourceItem::Source() + { + return iSource; + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::Sink +// ----------------------------------------------------------------------------- +// +MDataSink* CMccResourceItem::Sink() + { + return iSink; + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::MultiplexerL +// ----------------------------------------------------------------------------- +// +CMccMultiplexer* CMccResourceItem::MultiplexerL() + { + if ( !iMultiplexerItem ) + { + iMultiplexerItem = + CMccResourceItem::NewL( iCurrentUserStreamId, + iSink, + iSource, + iEndpointId, + ETrue ); + + // Update ref count immediately + for ( TInt i = 0; i < iUsers.Count(); i++ ) + { + User::LeaveIfError( + iMultiplexerItem->IncreaseRefCount( iUsers[ i ] ) ); + } + } + return iMultiplexerItem->GetMultiplexerL(); + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::GetMultiplexerL +// ----------------------------------------------------------------------------- +// +CMccMultiplexer* CMccResourceItem::GetMultiplexerL() + { + __ASSERT_ALWAYS( iMultiplexer, User::Leave( KErrNotReady ) ); + + return iMultiplexer; + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::UserSessionMatch +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::UserSessionMatch( + const TMccResourceParams& aUser1, + const TMccResourceParams& aUser2 ) + { + return ( aUser1.iSessionId == aUser2.iSessionId ); + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::UserMatch +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::UserMatch( + const TMccResourceParams& aUser1, + const TMccResourceParams& aUser2 ) + { + return ( aUser1.iStreamId == aUser2.iStreamId ); + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::UserMatchNotStrict +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::UserMatchNotStrict( + const TMccResourceParams& aUser1, + const TMccResourceParams& aUser2 ) + { + if ( aUser1.iLinkId ) + { + return ( aUser1.iLinkId == aUser2.iLinkId ); + } + return UserMatch( aUser1, aUser2 ); + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::UserMatchActive +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::UserMatchActive( + const TMccResourceParams& /*aUser1*/, + const TMccResourceParams& aUser2 ) + { + // First argument is the search term, in this case it can be ignored + return ( !aUser2.iIsStopped ); + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::UsersInfoL +// ----------------------------------------------------------------------------- +// +void CMccResourceItem::UsersInfoL( RArray& aUsers ) + { + for ( TInt i = 0; i < iUsers.Count(); i++ ) + { + aUsers.AppendL( iUsers[ i ] ); + } + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::CurrentState +// ----------------------------------------------------------------------------- +// +MMccResources::TResourceState CMccResourceItem::CurrentState() const + { + return iState; + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::Match +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::Match( const TMccResourceParams& aUser ) const + { + TIdentityRelation comparison( UserMatchNotStrict ); + TInt index = iUsers.Find( aUser, comparison ); + return ( index != KErrNotFound ); + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::MatchSession +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::MatchSession( const TUint32 aSessionId ) const + { + TMccResourceParams searchTerm( aSessionId, 0, 0, 0, EFalse, 0 ); + TIdentityRelation comparison( UserSessionMatch ); + TInt index = iUsers.Find( searchTerm, comparison ); + return ( index != KErrNotFound ); + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::StoreKeyFrameInfoL +// ----------------------------------------------------------------------------- +// +void CMccResourceItem::StoreKeyFrameInfoL( CMMFBuffer& aKeyFrame ) + { + __CONTROLLER_INT1( "CMccResourceItem::StoreKeyFrameInfoL, timestamp:", + aKeyFrame.TimeToPlay().Int64() ) + + if ( iKeyFrameInfo.Count() >= KMccMaxNumKeyFrames ) + { + iKeyFrameInfo.Remove( 0 ); + iKeyFrameInfo.Compress(); + } + TMccKeyFrameInfo info; + info.iSeqNum = aKeyFrame.FrameNumber(); + info.iTimestamp = aKeyFrame.TimeToPlay().Int64(); + iKeyFrameInfo.AppendL( info ); + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::IsKeyFrame +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::IsKeyFrame( CMMFBuffer& aBuffer ) + { + TBool isKeyFrame( EFalse ); + for ( TInt i = 0; i < iKeyFrameInfo.Count() && !isKeyFrame; i++ ) + { + TMccKeyFrameInfo& info = iKeyFrameInfo[ i ]; + isKeyFrame = ( info.iSeqNum == aBuffer.FrameNumber() && + info.iTimestamp == aBuffer.TimeToPlay().Int64() ); + } + return isKeyFrame; + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::IsCurrentUser +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::IsCurrentUser( TUint32 aStreamId ) const + { + return ( iCurrentUserStreamId == aStreamId ); + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::NonSharableResource +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::NonSharableResource( TUid aUid ) const + { + // TBD! sharing audiooutput should be possible with multiplexer + return ( aUid == KUidMmfAudioInput || + aUid == KUidMmfAudioOutput ); + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::IsInternal +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::IsInternal( TUint32 aUid ) const + { + return MCC_INTERNAL_ENDPOINT( aUid ); + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::CMccResourceItem +// ----------------------------------------------------------------------------- +// +CMccResourceItem::CMccResourceItem( + TUint32 aCurrentUserStreamId, + TUint32 aEndpointId, + TBool aIsMultiplexer ) : + iCurrentUserStreamId( aCurrentUserStreamId ), + iEndpointId( aEndpointId ), + iIsMultiplexer( aIsMultiplexer ) + { + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::ConstructL +// ----------------------------------------------------------------------------- +// +void CMccResourceItem::ConstructL( + MDataSink* aSink, + MDataSource* aSource ) + { + __CONTROLLER( "CMccResourceItem::ConstructL" ) + + // Resource item can contain sink OR source + + if ( aSink ) + { + __ASSERT_ALWAYS( !aSource, User::Leave( KErrArgument ) ); + iSink = aSink; + } + else if ( aSource ) + { + __ASSERT_ALWAYS( !aSink, User::Leave( KErrArgument ) ); + iSource = aSource; + } + else + { + User::Leave( KErrArgument ); + } + + if ( iIsMultiplexer ) + { + __CONTROLLER( "CMccResourceItem::ConstructL, create real multiplexer" ) + + __ASSERT_ALWAYS( iSource, User::Leave( KErrNotReady ) ); + iMultiplexer = CMccMultiplexer::NewL( iSource ); + } + + __CONTROLLER( "CMccResourceItem::ConstructL, exit" ) + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::SpecialStateChangeL +// ----------------------------------------------------------------------------- +// +void CMccResourceItem::SpecialStateChangeL( + TUint32 aStreamId, + MMccResources::TResourceState aState, + TBool aStandbyControl, + TBool aDtmfControl, + TBool& aEffectiveStateChange ) + { + __CONTROLLER( "CMccResourceItem::StandbyStateChangeL" ) + __CONTROLLER_INT1( "CMccResourceItem::StandbyStateChangeL, paused by user:", + iPausedByUser ) + __CONTROLLER_INT1( "CMccResourceItem::StandbyStateChangeL, standby control:", + aStandbyControl ) + + // For standby resource, pausing prepared resource is ok but it's not + // an effective state change as pause is not really needed. If standby + // resource has been paused by user, standby control will not have + // any effect. Additionally, user paused stream is not resumed if user + // tries to do it. Dtmf stream cannot pause its endpoints if others are + // using them. + + TBool stateOK( EFalse ); + + TBool nonEffective = + ( iPausedByUser && aStandbyControl ) || + ( !aStandbyControl && !aDtmfControl && aState == MMccResources::EStarted ) || + ( aDtmfControl && aStandbyControl && aState == MMccResources::EResourcePaused && + ( RefCount() > KMccOneResourceUser ) ); + + switch ( aState ) + { + case MMccResources::EPrepared: + { + if ( MMccResources::EConstructed == iState ) + { + stateOK = ETrue; + } + else if ( iState == MMccResources::EStarted || + iState == MMccResources::EResourcePaused ) + { + // Endpoint is already started by other user, + // state is not "downgraded" + aState = iState; + stateOK = ETrue; + } + else + { + // NOP + } + break; + } + case MMccResources::EStarted: + { + if ( MMccResources::EPrepared == iState || + MMccResources::EResourcePaused == iState ) + { + stateOK = ETrue; + } + break; + } + case MMccResources::EResourcePaused: + { + if ( MMccResources::EStarted == iState ) + { + stateOK = ETrue; + } + else if ( MMccResources::EPrepared == iState ) + { + stateOK = ETrue; + nonEffective = ETrue; + } + else + { + } + + break; + } + case MMccResources::EResourceStopped: + { + nonEffective = !UserStopL( aStreamId ); + stateOK = ETrue; + break; + } + default: + { + break; + } + } + + if ( aState != iState ) + { + if ( !nonEffective ) + { + __ASSERT_ALWAYS( stateOK, User::Leave( KErrNotReady ) ); + + iState = aState; + } + + aEffectiveStateChange = !nonEffective; + } + + if ( !aStandbyControl ) + { + // Update paused by user info + iPausedByUser = ( MMccResources::EResourcePaused == aState || + MMccResources::EPrepared == aState ); + } + + __CONTROLLER( "CMccResourceItem::StandbyStateChangeL, exit" ) + } + +// ----------------------------------------------------------------------------- +// CMccResourceItem::UserStopL +// ----------------------------------------------------------------------------- +// +TBool CMccResourceItem::UserStopL( TUint32 aStreamId ) + { + TMccResourceParams searchTerm( 0, 0, aStreamId, 0, EFalse, 0 ); + TIdentityRelation comparison( UserMatch ); + TInt index = iUsers.Find( searchTerm, comparison ); + __ASSERT_ALWAYS( index != KErrNotFound, User::Leave( KErrNotFound ) ); + iUsers[ index ].iIsStopped = ETrue; + + TIdentityRelation comparison2( UserMatchActive ); + index = iUsers.Find( searchTerm, comparison2 ); + + // If didn't found any active ones, the resource can be stopped + return ( index == KErrNotFound ); + } + +// End of file +