multimediacommscontroller/mmccmultiplexer/src/mccsinkitem.cpp
changeset 0 1bce908db942
equal deleted inserted replaced
-1:000000000000 0:1bce908db942
       
     1 /*
       
     2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:   
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 // INCLUDE FILES
       
    22 #include <mmf/server/mmfdatasink.h>
       
    23 #include <mmf/server/mmfbuffer.h>
       
    24 #include "rtpheader.h"
       
    25 #include "mccsinkitem.h"
       
    26 #include "formatstatemachine.h"
       
    27 #include "mccmultiplexerlogs.h"
       
    28 #include "mccinternaldef.h"
       
    29 #include "mccinternalevents.h"
       
    30 #include "mccuids.hrh"
       
    31 
       
    32 // MACROS
       
    33 
       
    34 #define MCC_PAYLOAD_READ( a ) static_cast<CPayloadFormatRead*>( a )
       
    35 
       
    36 // LOCAL FUNCTION PROTOTYPES
       
    37 
       
    38 // LOCAL CONSTANTS
       
    39 
       
    40 const TInt KMccBadDataCount = 20;
       
    41 
       
    42 const TInt KMccMaxStoredBuffers = 10;
       
    43 
       
    44 // ============================= LOCAL FUNCTIONS ===============================
       
    45 
       
    46 // ============================ MEMBER FUNCTIONS ===============================
       
    47 
       
    48 // -----------------------------------------------------------------------------
       
    49 // CMccSinkItem::NewLC
       
    50 // -----------------------------------------------------------------------------
       
    51 //
       
    52 CMccSinkItem* CMccSinkItem::NewLC( 
       
    53     MDataSink* aSink, 
       
    54     TBool aSinkIsDecoder,
       
    55     TUid aMediaType,
       
    56     TBool aPassAllBuffersSink )
       
    57     {
       
    58     CMccSinkItem* self = 
       
    59         new ( ELeave ) CMccSinkItem( aMediaType, aPassAllBuffersSink );
       
    60     CleanupStack::PushL( self );
       
    61     self->ConstructL( aSink, aSinkIsDecoder );
       
    62     return self;
       
    63     }
       
    64 
       
    65 // -----------------------------------------------------------------------------
       
    66 // CMccSinkItem::~CMccSinkItem
       
    67 // -----------------------------------------------------------------------------
       
    68 //    
       
    69 CMccSinkItem::~CMccSinkItem()
       
    70     {
       
    71     iStoredBuffers.ResetAndDestroy();
       
    72     iPayloadsToAccept.Close();
       
    73     }
       
    74 
       
    75 // -----------------------------------------------------------------------------
       
    76 // CMccSinkItem::BufferFilledL
       
    77 // -----------------------------------------------------------------------------
       
    78 //    
       
    79 void CMccSinkItem::BufferFilledL( 
       
    80     CMMFBuffer* aBuffer, 
       
    81     const TRtpRecvHeader* aHeaderInfo,
       
    82     TBool aPrimary,
       
    83     TUid aMediaType )
       
    84     {
       
    85     __MULTIPLEXER_INT1( "CMccSinkItem::BufferFilledL, sinkitem:", 
       
    86                         reinterpret_cast<TUint32>( this ) )
       
    87 
       
    88     CMMFBuffer* completedBuffer = NULL;
       
    89     
       
    90     CMMFDataBuffer* dataBuffer = static_cast<CMMFDataBuffer*>( aBuffer );
       
    91     
       
    92     if ( aMediaType != KNullUid && MediaType() != aMediaType )
       
    93         {
       
    94         __MULTIPLEXER( "CMccSinkItem::BufferFilledL, wrong media type" )
       
    95         return;
       
    96         }
       
    97     
       
    98     if ( HandleBadDataL( dataBuffer ) )
       
    99         {
       
   100         __MULTIPLEXER( "CMccSinkItem::BufferFilledL, stopping buffer forwarding" )
       
   101         return;
       
   102         }
       
   103     
       
   104     if ( aHeaderInfo
       
   105         && ( KErrNotFound != iPayloadsToAccept.Find( aHeaderInfo->iPayloadType ) ) )
       
   106         {
       
   107         __MULTIPLEXER( "CMccSinkItem::BufferFilledL, payload type demultiplexing" )
       
   108         
       
   109         if ( iRequestedBuffer )
       
   110             {
       
   111             __MULTIPLEXER( "CMccSinkItem::BufferFilledL, fillbuffer request exists" )
       
   112             
       
   113             CopyBufferL( iRequestedBuffer, aBuffer );
       
   114             completedBuffer = iRequestedBuffer;
       
   115             iRequestedBuffer = NULL;
       
   116             }
       
   117         }
       
   118     else if ( iPassAllBuffersSink )
       
   119         {
       
   120         __MULTIPLEXER( "CMccSinkItem::BufferFilledL, in passall buffers mode" )
       
   121         
       
   122         // Do not zero the request, sink will eat all buffers
       
   123         // once it has requested for one
       
   124         if ( iRequestedBuffer )
       
   125             {
       
   126             completedBuffer = aBuffer;
       
   127             }
       
   128         }
       
   129     else if ( iPassAllRequestsSource )
       
   130         {
       
   131         __MULTIPLEXER( "CMccSinkItem::BufferFilledL, in passall requests mode" )
       
   132         
       
   133         // If in passall mode, buffer received from source must match with the
       
   134         // one the sink gave when requesting the buffer fill
       
   135         if ( iRequestedBuffer &&
       
   136              iRequestedBuffer == aBuffer )
       
   137             {
       
   138             __MULTIPLEXER( "CMccSinkItem::BufferFilledL, existing fillbuffer request" )
       
   139             
       
   140             completedBuffer = aBuffer;
       
   141             iRequestedBuffer = NULL;
       
   142             }
       
   143         }
       
   144     else if ( iRequestedBuffer && aPrimary )
       
   145         {
       
   146         __MULTIPLEXER( "CMccSinkItem::BufferFilledL, existing fillbuffer request for primary" )
       
   147         
       
   148         completedBuffer = aBuffer;
       
   149         iRequestedBuffer = NULL;
       
   150         }
       
   151     else
       
   152         {
       
   153         if ( iRequestedBuffer )
       
   154             {
       
   155             __MULTIPLEXER( "CMccSinkItem::BufferFilledL, existing fillbuffer request" )
       
   156             
       
   157             // If secondary sink has already requested buffer fill, the request
       
   158             // can be completed immediately
       
   159             CopyBufferL( iRequestedBuffer, aBuffer );
       
   160             completedBuffer = iRequestedBuffer;
       
   161             iRequestedBuffer = NULL;
       
   162             }
       
   163         else
       
   164             {
       
   165             // Otherwise the buffer has to be "stored"
       
   166             StoreBufferL( aBuffer );
       
   167             }
       
   168         }
       
   169     
       
   170     if ( completedBuffer )
       
   171         {    
       
   172         if ( iDecoder && aHeaderInfo )
       
   173             {
       
   174             iDecoder->DataBufferFilledL( completedBuffer, *aHeaderInfo );
       
   175             }
       
   176         else
       
   177             {
       
   178             Sink()->BufferFilledL( completedBuffer );
       
   179             }
       
   180         }
       
   181         
       
   182     __MULTIPLEXER( "CMccSinkItem::BufferFilledL, exit" )
       
   183     }
       
   184 
       
   185 // -----------------------------------------------------------------------------
       
   186 // CMccSinkItem::FillBufferRequestL
       
   187 // -----------------------------------------------------------------------------
       
   188 //    
       
   189 void CMccSinkItem::FillBufferRequestL( CMMFBuffer* aBuffer )
       
   190     {
       
   191     __MULTIPLEXER_INT1( "CMccSinkItem::FillBufferRequestL, sinkitem:", 
       
   192                         reinterpret_cast<TUint32>( this ) )
       
   193     
       
   194     CMMFBuffer* storedBuffer = GetStoredBuffer();
       
   195     if ( storedBuffer )
       
   196         {
       
   197         __MULTIPLEXER( "CMccSinkItem::FillBufferRequestL, stored buffer exists" )
       
   198         
       
   199         CleanupStack::PushL( storedBuffer );
       
   200         CopyBufferL( aBuffer, storedBuffer );
       
   201         CleanupStack::PopAndDestroy( storedBuffer );
       
   202         
       
   203         Sink()->BufferFilledL( aBuffer );
       
   204         }
       
   205     else
       
   206         {
       
   207         __MULTIPLEXER( "CMccSinkItem::FillBufferRequestL, store fillbuffer request" )
       
   208         
       
   209         iRequestedBuffer = aBuffer;
       
   210         }
       
   211         
       
   212     __MULTIPLEXER( "CMccSinkItem::FillBufferRequestL, exit" )
       
   213     }
       
   214 
       
   215 // -----------------------------------------------------------------------------
       
   216 // CMccSinkItem::Match
       
   217 // -----------------------------------------------------------------------------
       
   218 //                            
       
   219 TBool CMccSinkItem::Match( MDataSink* aSink )
       
   220     {
       
   221     return ( Sink() == aSink );
       
   222     }
       
   223 
       
   224 // -----------------------------------------------------------------------------
       
   225 // CMccSinkItem::SourceThreadLogon
       
   226 // -----------------------------------------------------------------------------
       
   227 //
       
   228 TInt CMccSinkItem::SourceThreadLogon( MAsyncEventHandler& aEventHandler )
       
   229     {
       
   230     iEventHandler = &aEventHandler;
       
   231     return KErrNone;
       
   232     }
       
   233     
       
   234 // -----------------------------------------------------------------------------
       
   235 // CMccSinkItem::SendEventToClient
       
   236 // -----------------------------------------------------------------------------
       
   237 //    
       
   238 TInt CMccSinkItem::SendEventToClient( const TMMFEvent& aEvent )
       
   239     {
       
   240     __MULTIPLEXER( "CMccSinkItem::SendEventToClient" )
       
   241     
       
   242     // Filter duplicate stream state change events. Errors are always reported.
       
   243     // Check also whether the event is targeted for specific payload type.
       
   244     //
       
   245     
       
   246     TInt ret( KErrNotReady );
       
   247     TBool sendEvent( ETrue );
       
   248 
       
   249   	if ( IS_MCC_EVENT( aEvent ) )
       
   250 	    {
       
   251 	    TMccEvent* mccEventPtr = 
       
   252 	        reinterpret_cast<const TMccInternalEvent&>( aEvent ).iMccEvent;  
       
   253 	        
       
   254 	    if ( mccEventPtr && MCC_STREAM_STATE_CHANGE_EVENT( mccEventPtr ) &&
       
   255 	         !mccEventPtr->iErrorCode )
       
   256 	        {
       
   257 	        sendEvent = HandleStreamStateChangeEvent( *mccEventPtr );
       
   258 	        ret = KErrNone;
       
   259 	        }
       
   260 	    else if ( mccEventPtr && 
       
   261 	              mccEventPtr->iEventNumData == KMccPayloadSpecificEvent &&
       
   262 	              mccEventPtr->iReserved != KMccPTNotDefined )
       
   263 	        {
       
   264 	        __MULTIPLEXER_INT1( "CMccSinkItem::SendEventToClient, event for payload type:",
       
   265 	                            mccEventPtr->iReserved )
       
   266 	                            
       
   267 	        sendEvent = 
       
   268 	            ( iPayloadsToAccept.Find( mccEventPtr->iReserved ) != KErrNotFound );
       
   269 	        }
       
   270 	    else
       
   271 	        {
       
   272 	        // NOP
       
   273 	        }
       
   274 	    }
       
   275     
       
   276     if ( iEventHandler && sendEvent )
       
   277         {
       
   278         ret = iEventHandler->SendEventToClient( aEvent );
       
   279         }
       
   280     else
       
   281         {
       
   282         __MULTIPLEXER( "CMccSinkItem::SendEventToClient, dropping event" )
       
   283         }
       
   284     return ret;
       
   285     }
       
   286 
       
   287 // -----------------------------------------------------------------------------
       
   288 // CMccSinkItem::MediaType
       
   289 // -----------------------------------------------------------------------------
       
   290 //     
       
   291 TUid CMccSinkItem::MediaType() const
       
   292     {
       
   293     return iMediaType;
       
   294     }
       
   295     
       
   296 // -----------------------------------------------------------------------------
       
   297 // CMccSinkItem::RegisterPayloadTypesL
       
   298 // -----------------------------------------------------------------------------
       
   299 //     
       
   300 void CMccSinkItem::RegisterPayloadTypesL( const RArray<TUint>& aPayloadTypes )
       
   301     {
       
   302     __MULTIPLEXER( "CMccSinkItem::RegisterPayloadTypesL" )
       
   303     
       
   304     TInt ind = aPayloadTypes.Count();
       
   305     while ( ind-- )
       
   306         {
       
   307         if ( KErrNotFound == iPayloadsToAccept.Find( aPayloadTypes[ind]) )
       
   308             {
       
   309             iPayloadsToAccept.AppendL( aPayloadTypes[ind] );
       
   310             }
       
   311         else
       
   312             {
       
   313             User::Leave( KErrAlreadyExists );
       
   314             }
       
   315         }
       
   316     }
       
   317 
       
   318 // -----------------------------------------------------------------------------
       
   319 // CMccSinkItem::RegisteredPayloadTypes
       
   320 // -----------------------------------------------------------------------------
       
   321 //
       
   322 const RArray<TUint>& CMccSinkItem::RegisteredPayloadTypes() const
       
   323     {
       
   324     return iPayloadsToAccept;
       
   325     }
       
   326 
       
   327 // -----------------------------------------------------------------------------
       
   328 // CMccSinkItem::RequestedBuffer
       
   329 // -----------------------------------------------------------------------------
       
   330 //
       
   331 CMMFBuffer* CMccSinkItem::RequestedBuffer()
       
   332     {
       
   333     return iRequestedBuffer;
       
   334     }
       
   335 
       
   336 // -----------------------------------------------------------------------------
       
   337 // CMccSinkItem::EventHandler
       
   338 // -----------------------------------------------------------------------------
       
   339 //
       
   340 MAsyncEventHandler* CMccSinkItem::EventHandler()
       
   341     {
       
   342     return iEventHandler;
       
   343     }
       
   344 
       
   345 // -----------------------------------------------------------------------------
       
   346 // CMccSinkItem::SetMultiplexerState
       
   347 // -----------------------------------------------------------------------------
       
   348 //
       
   349 void CMccSinkItem::SetMultiplexerState( CMccMultiplexer::TMccMultiplexerState aState )
       
   350     {
       
   351     __MULTIPLEXER_INT2( "CMccSinkItem::SetMultiplexerState, sinkitem:", 
       
   352                         reinterpret_cast<TUint32>( this ),
       
   353                         " state:", aState )
       
   354     iState = aState;
       
   355     }
       
   356 
       
   357 // -----------------------------------------------------------------------------
       
   358 // CMccSinkItem::MultiplexerState
       
   359 // -----------------------------------------------------------------------------
       
   360 //
       
   361 CMccMultiplexer::TMccMultiplexerState CMccSinkItem::MultiplexerState() const
       
   362     {
       
   363     return iState;
       
   364     }
       
   365     
       
   366 // -----------------------------------------------------------------------------
       
   367 // CMccSinkItem::SetSourceMode
       
   368 // -----------------------------------------------------------------------------
       
   369 //    
       
   370 void CMccSinkItem::SetSourceMode( TBool aPassAllRequestsSource )
       
   371     {
       
   372     __MULTIPLEXER_INT1( "CMccSinkItem::SetSourceMode, sinkitem:", 
       
   373                         reinterpret_cast<TUint32>( this ) )
       
   374     __MULTIPLEXER_INT1( "CMccSinkItem::SetSourceMode, mediatype:", 
       
   375                         iMediaType.iUid )
       
   376     __MULTIPLEXER_INT1( "CMccSinkItem::SetSourceMode, mode:", 
       
   377                         aPassAllRequestsSource )
       
   378     
       
   379     iPassAllRequestsSource = aPassAllRequestsSource;
       
   380     }
       
   381 
       
   382 // -----------------------------------------------------------------------------
       
   383 // CMccSinkItem::PassAllRequestsToSource
       
   384 // -----------------------------------------------------------------------------
       
   385 //     
       
   386 TBool CMccSinkItem::PassAllRequestsToSource() const
       
   387     {
       
   388     return iPassAllRequestsSource;
       
   389     }
       
   390 
       
   391 // -----------------------------------------------------------------------------
       
   392 // CMccSinkItem::CMccSinkItem
       
   393 // -----------------------------------------------------------------------------
       
   394 //     
       
   395 TUid CMccSinkItem::ResolveMediaType( CMMFBuffer* aBuffer ) const
       
   396     {
       
   397     if ( aBuffer && iPassAllRequestsSource && iRequestedBuffer == aBuffer )
       
   398         {
       
   399         return MediaType();
       
   400         }
       
   401     return KNullUid;
       
   402     }
       
   403     
       
   404 // -----------------------------------------------------------------------------
       
   405 // CMccSinkItem::CMccSinkItem
       
   406 // -----------------------------------------------------------------------------
       
   407 //   
       
   408 CMccSinkItem::CMccSinkItem( TUid aMediaType, TBool aPassAllBuffersSink ) :
       
   409     iMediaType( aMediaType ),
       
   410     iPassAllBuffersSink( aPassAllBuffersSink ),
       
   411     iReportedEvent( KMccEventNone ), iBadDataCount( 0 )
       
   412     {
       
   413     }
       
   414 
       
   415 // -----------------------------------------------------------------------------
       
   416 // CMccSinkItem::Sink
       
   417 // -----------------------------------------------------------------------------
       
   418 //       
       
   419 void CMccSinkItem::ConstructL( MDataSink* aSink, TBool aSinkIsDecoder )
       
   420     {
       
   421     __MULTIPLEXER( "CMccSinkItem::ConstructL" )
       
   422     
       
   423     __ASSERT_ALWAYS( aSink, User::Leave( KErrArgument ) );
       
   424     
       
   425     if ( aSinkIsDecoder )
       
   426         {
       
   427         __MULTIPLEXER( "CMccSinkItem::ConstructL, sink is decoder" )
       
   428         
       
   429         CMMFFormatDecode* decoder = static_cast<CMMFFormatDecode*>( aSink ); 
       
   430         
       
   431         iDecoder = MCC_PAYLOAD_READ( decoder );
       
   432         }
       
   433     else
       
   434         {
       
   435         iSink = aSink;
       
   436         }
       
   437         
       
   438     __MULTIPLEXER( "CMccSinkItem::ConstructL, exit" )
       
   439     }
       
   440 
       
   441 // -----------------------------------------------------------------------------
       
   442 // CMccSinkItem::Sink
       
   443 // -----------------------------------------------------------------------------
       
   444 //    
       
   445 MDataSink* CMccSinkItem::Sink()
       
   446     {
       
   447     if ( iDecoder )
       
   448         {
       
   449         return iDecoder;
       
   450         }
       
   451     
       
   452     return iSink;
       
   453     }
       
   454     
       
   455 // ---------------------------------------------------------------------------
       
   456 // CMccSinkItem::CopyBufferL
       
   457 // ---------------------------------------------------------------------------
       
   458 //  
       
   459 void CMccSinkItem::CopyBufferL( 
       
   460     CMMFBuffer* aDesBuffer,
       
   461     CMMFBuffer* aOrigBuffer )
       
   462 	{
       
   463 	__ASSERT_ALWAYS( aDesBuffer && aOrigBuffer, User::Leave( KErrArgument ) );
       
   464 	
       
   465 	// Copy buffer setting
       
   466     aDesBuffer->SetFrameNumber( aOrigBuffer->FrameNumber() );
       
   467     aDesBuffer->SetLastBuffer( aOrigBuffer->LastBuffer() );
       
   468     aDesBuffer->SetPosition( aOrigBuffer->Position() );
       
   469      // Note: setting the status to available clears the buffer data
       
   470     aDesBuffer->SetStatus( aOrigBuffer->Status() );
       
   471     aDesBuffer->SetTimeToPlay( aOrigBuffer->TimeToPlay() );
       
   472     	
       
   473 	// Copy buffer data
       
   474 	CMMFDataBuffer* desBuffer = static_cast<CMMFDataBuffer*>( aDesBuffer );
       
   475 	CMMFDataBuffer* origBuffer = static_cast<CMMFDataBuffer*>( aOrigBuffer );
       
   476 	
       
   477 	__ASSERT_ALWAYS( desBuffer->Data().MaxLength() >= (TInt) origBuffer->BufferSize(), 
       
   478 	                 User::Leave( KErrOverflow ) );
       
   479 	
       
   480     desBuffer->Data().Copy( origBuffer->Data() );
       
   481 	}
       
   482 
       
   483 // ---------------------------------------------------------------------------
       
   484 // CMccSinkItem::IsInternalDecoder
       
   485 // ---------------------------------------------------------------------------
       
   486 //  
       
   487 TBool CMccSinkItem::IsInternalDecoder( TUid aDecoderUid ) const
       
   488     {
       
   489     TUint32 decoderUid = aDecoderUid.iUid;
       
   490     return ( decoderUid == KImplUidAmrPayloadFormatDecode ||
       
   491              decoderUid == KImplUidAnyPayloadFormatDecode ||
       
   492              decoderUid == KImplUidDTMFPayloadFormatDecode ||
       
   493              decoderUid == KImplUidRedPayloadFormatDecode );
       
   494     
       
   495     }
       
   496 
       
   497 // ---------------------------------------------------------------------------
       
   498 // CMccSinkItem::StoreBufferL
       
   499 // ---------------------------------------------------------------------------
       
   500 //     
       
   501 void CMccSinkItem::StoreBufferL( CMMFBuffer* aBuffer )
       
   502     {
       
   503     __MULTIPLEXER( "CMccSinkItem::StoreBufferL" )
       
   504     
       
   505     // If secondary sink has not yet requested buffer fill, the buffer
       
   506     // will be stored
       
   507     if ( iStoredBuffers.Count() >= KMccMaxStoredBuffers )
       
   508         {
       
   509         __MULTIPLEXER( "CMccSinkItem::BufferFilledL, dropping oldest stored buffer!" )
       
   510         delete iStoredBuffers[ 0 ];
       
   511         iStoredBuffers.Remove( 0 );
       
   512         }
       
   513     
       
   514     CMMFDataBuffer* storedBuffer = CMMFDataBuffer::NewL( aBuffer->BufferSize() );
       
   515     
       
   516     CleanupStack::PushL( storedBuffer );
       
   517     CopyBufferL( storedBuffer, aBuffer ); 
       
   518     iStoredBuffers.AppendL( storedBuffer );
       
   519     CleanupStack::Pop( storedBuffer );
       
   520     
       
   521     __MULTIPLEXER( "CMccSinkItem::StoreBufferL, exit" )
       
   522     }
       
   523 
       
   524 // ---------------------------------------------------------------------------
       
   525 // CMccSinkItem::GetStoredBuffer
       
   526 // ---------------------------------------------------------------------------
       
   527 //   
       
   528 CMMFBuffer* CMccSinkItem::GetStoredBuffer()
       
   529     {
       
   530     CMMFBuffer* buffer = NULL;
       
   531     
       
   532     if ( iStoredBuffers.Count() > 0 )
       
   533         {
       
   534         buffer = iStoredBuffers[ 0 ];
       
   535         iStoredBuffers.Remove( 0 );
       
   536         }
       
   537         
       
   538     return buffer;
       
   539     }
       
   540 
       
   541 // ---------------------------------------------------------------------------
       
   542 // CMccSinkItem::HandleBadData
       
   543 // ---------------------------------------------------------------------------
       
   544 // 
       
   545 TBool CMccSinkItem::HandleBadDataL( CMMFDataBuffer* aBuffer )
       
   546     { 
       
   547     TBool stopBufferForwarding( EFalse ); 
       
   548     if ( aBuffer == NULL || !aBuffer->BufferSize() )
       
   549         {
       
   550         __MULTIPLEXER( "CMccSinkItem::HandleBadDataL, bad data received" )
       
   551         iBadDataCount++;
       
   552         if ( iBadDataCount >= KMccBadDataCount && iEventHandler )
       
   553             {
       
   554             __MULTIPLEXER( "CMccSinkItem::HandleBadDataL, pausing stream" )
       
   555             iBadDataCount = 0;
       
   556             
       
   557     	    TMccEvent* event = new ( ELeave ) TMccEvent;
       
   558 	        CleanupStack::PushL( event );
       
   559     	    event->iEndpointId = 0;
       
   560     	    event->iEventCategory = KMccEventCategoryStreamControl;
       
   561     	    event->iEventType = KMccStreamPaused;
       
   562     	    event->iErrorCode = KErrNone;
       
   563 
       
   564     		TMccInternalEvent internalEvent( KMccMultiplexerUid, EMccInternalEventNone,
       
   565     		                                 *event );
       
   566 		                         
       
   567 		    User::LeaveIfError( iEventHandler->SendEventToClient( internalEvent ) );
       
   568 		    
       
   569 		    CleanupStack::PopAndDestroy( event );
       
   570             __MULTIPLEXER( "CMccSinkItem::HandleBadDataL, pausing event sent" )
       
   571             
       
   572             stopBufferForwarding = ETrue;
       
   573             }
       
   574         }
       
   575     else    
       
   576         {
       
   577         iBadDataCount = 0;
       
   578         }
       
   579         
       
   580     return stopBufferForwarding;
       
   581     }
       
   582 
       
   583 // ---------------------------------------------------------------------------
       
   584 // CMccSinkItem::HandleStreamStateChangeEvent
       
   585 // ---------------------------------------------------------------------------
       
   586 //
       
   587 TBool CMccSinkItem::HandleStreamStateChangeEvent( TMccEvent& aEvent )
       
   588     {
       
   589     TBool sendEvent( ETrue );
       
   590     
       
   591     // Modify started event to resumed event if previously paused
       
   592     if ( aEvent.iEventType == KMccStreamStarted && 
       
   593          iReportedEvent == KMccStreamPaused )
       
   594         {
       
   595         __MULTIPLEXER( "CMccSinkItem::SendEventToClient, modify event type" )
       
   596         aEvent.iEventType = KMccStreamResumed;
       
   597         }
       
   598     
       
   599     // Automatic started/resumed event is not forwarded if this user hasn't yet
       
   600     // started the source
       
   601     if ( aEvent.iEventNumData == KMccAutomaticEvent &&
       
   602        ( aEvent.iEventType == KMccStreamStarted ||
       
   603          aEvent.iEventType == KMccStreamResumed ) )
       
   604         {
       
   605         sendEvent = ( iState >= CMccMultiplexer::EPlaying );
       
   606         
       
   607         __MULTIPLEXER_INT1( 
       
   608         "CMccSinkItem::SendEventToClient, automatic event send:", sendEvent )
       
   609         }
       
   610     
       
   611     if ( sendEvent )
       
   612         {
       
   613         sendEvent = ( aEvent.iEventType != iReportedEvent );
       
   614         
       
   615         iReportedEvent = aEvent.iEventType;
       
   616         }
       
   617     
       
   618     return sendEvent;
       
   619     }
       
   620     
       
   621 //  End of File 
       
   622