--- /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 <mmf/server/mmfaudioinput.h>
+#include <mmf/server/mmfaudiooutput.h>
+
+// 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<TMccResourceParams> 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<TMccResourceParams>& 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<TMccResourceParams> 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<TMccResourceParams> 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<TMccResourceParams> comparison( UserMatch );
+ TInt index = iUsers.Find( searchTerm, comparison );
+ __ASSERT_ALWAYS( index != KErrNotFound, User::Leave( KErrNotFound ) );
+ iUsers[ index ].iIsStopped = ETrue;
+
+ TIdentityRelation<TMccResourceParams> 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
+