multimediacommscontroller/mmccsubcontroller/src/mccdldatapath.cpp
changeset 0 1bce908db942
child 49 64c62431ac08
equal deleted inserted replaced
-1:000000000000 0:1bce908db942
       
     1 /*
       
     2 * Copyright (c) 2004-2007 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:    Downlink (playback) datapath
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 
       
    21 // INCLUDE FILES
       
    22 #include <mmf/common/mmfcontroller.h>
       
    23 #include "mccdldatapath.h"
       
    24 #include "mccsubcontrollerlogs.h"
       
    25 
       
    26 // EXTERNAL DATA STRUCTURES
       
    27 
       
    28 // EXTERNAL FUNCTION PROTOTYPES  
       
    29 
       
    30 // CONSTANTS
       
    31 
       
    32 // MACROS
       
    33 
       
    34 // LOCAL CONSTANTS AND MACROS
       
    35 
       
    36 // MODULE DATA STRUCTURES
       
    37 
       
    38 // LOCAL FUNCTION PROTOTYPES
       
    39 
       
    40 // FORWARD DECLARATIONS
       
    41 
       
    42 // ============================= LOCAL FUNCTIONS ===============================
       
    43 
       
    44 // ============================ MEMBER FUNCTIONS ===============================
       
    45 
       
    46 // -----------------------------------------------------------------------------
       
    47 // CMccDlDataPath::CMccDlDataPath
       
    48 // C++ default constructor can NOT contain any code, that
       
    49 // might leave.
       
    50 // -----------------------------------------------------------------------------
       
    51 CMccDlDataPath::CMccDlDataPath( 
       
    52     MAsyncEventHandler* aEventHandler, 
       
    53     MMccResources* aMccResources,
       
    54     TMediaId aMediaId ) : 
       
    55     CMccDataPathBase( aEventHandler, aMccResources, aMediaId )
       
    56     {
       
    57 
       
    58     }
       
    59 
       
    60 // -----------------------------------------------------------------------------
       
    61 // CMccDlDataPath::ConstructL
       
    62 // Symbian 2nd phase constructor can leave.
       
    63 // -----------------------------------------------------------------------------
       
    64 void CMccDlDataPath::ConstructL()
       
    65     {
       
    66 	__SUBCONTROLLER( "CMccDlDataPath::ConstructL" )
       
    67 	__ASSERT_ALWAYS( iEventHandler, User::Leave( KErrArgument ) );
       
    68     __ASSERT_ALWAYS( iMccResources, User::Leave( KErrArgument ) );
       
    69 	__SUBCONTROLLER( "CMccDlDataPath::ConstructL, exit" )
       
    70     }
       
    71 
       
    72 // -----------------------------------------------------------------------------
       
    73 // CMccDlDataPath::NewL
       
    74 // Static constructor.
       
    75 // -----------------------------------------------------------------------------
       
    76 CMccDlDataPath* CMccDlDataPath::NewL( 
       
    77     MAsyncEventHandler* aEventHandler, 
       
    78     MMccResources* aMccResources,
       
    79     TMediaId aMediaId )
       
    80     {
       
    81     __ASSERT_ALWAYS ( aEventHandler, User::Leave(KErrArgument) );
       
    82     
       
    83     CMccDlDataPath* self = new ( ELeave ) CMccDlDataPath( aEventHandler,
       
    84                                                           aMccResources,
       
    85                                                           aMediaId );        
       
    86     CleanupStack::PushL( self );   
       
    87     self->ConstructL();   
       
    88     CleanupStack::Pop( self );
       
    89 
       
    90     return self;
       
    91     }
       
    92 
       
    93 // -----------------------------------------------------------------------------
       
    94 // CMccDlDataPath::~CMccDlDataPath
       
    95 // Destructor
       
    96 
       
    97 // -----------------------------------------------------------------------------  
       
    98 CMccDlDataPath::~CMccDlDataPath()
       
    99     {
       
   100 	__SUBCONTROLLER( "CMccDlDataPath::~CMccDlDataPath" )
       
   101 	__SUBCONTROLLER( "CMccDlDataPath::~CMccDlDataPath, exit" )
       
   102     }
       
   103 
       
   104 // -----------------------------------------------------------------------------
       
   105 // CMccDlDataPath::PrimeL
       
   106 // Primes the datapath
       
   107 // ----------------------------------------------------------------------------- 
       
   108 void CMccDlDataPath::PrimeL( TUint32 aEndpointId )
       
   109     {
       
   110     __SUBCONTROLLER( "CMccDlDataPath::PrimeL" )
       
   111     
       
   112     __ASSERT_ALWAYS( iDataPathCreated, User::Leave( KErrNotReady ) );	
       
   113 	__ASSERT_ALWAYS( iDataSource, User::Leave( KErrGeneral ) );
       
   114     __ASSERT_ALWAYS( iDataSink, User::Leave( KErrGeneral ) );
       
   115     
       
   116     if ( !iSourceBuffer )
       
   117         {
       
   118         TBool bufferReference;
       
   119         iSourceBuffer = 
       
   120             iDataSource->CreateSourceBufferL( iMediaId, bufferReference );
       
   121         __ASSERT_ALWAYS( iSourceBuffer, User::Leave( KErrGeneral ) );
       
   122         __ASSERT_ALWAYS( bufferReference, User::Leave( KErrGeneral ) );
       
   123         }
       
   124     
       
   125     if ( ControlSource( aEndpointId ) )
       
   126         {
       
   127         __SUBCONTROLLER( "CMccDlDataPath::PrimeL, control source" )
       
   128         
       
   129         SetStateL( EPrimed );
       
   130         
       
   131         iDataSource->NegotiateSourceL( *iDataSink );
       
   132         
       
   133         iDataSource->SourcePrimeL(); 
       
   134         }
       
   135     
       
   136     if ( ControlSink( aEndpointId ) )   
       
   137         {
       
   138         __SUBCONTROLLER( "CMccDlDataPath::PrimeL, control sink" )
       
   139         
       
   140         iDataSink->SinkPrimeL();
       
   141         }
       
   142         
       
   143     CreateCompleteCallBackL();
       
   144 
       
   145 	__SUBCONTROLLER( "CMccDlDataPath::PrimeL, exit" )
       
   146     }
       
   147 
       
   148 // -----------------------------------------------------------------------------
       
   149 // CMccDlDataPath::PauseL
       
   150 // Pauses the downlink streaming
       
   151 // -----------------------------------------------------------------------------
       
   152 void CMccDlDataPath::PauseL( TUint32 aEndpointId )
       
   153     {
       
   154 	__SUBCONTROLLER( "CMccDlDataPath::PauseL" )
       
   155 	
       
   156 	__ASSERT_ALWAYS( iDataPathCreated, User::Leave( KErrNotReady ) );
       
   157     __ASSERT_ALWAYS( iDataSource, User::Leave( KErrGeneral ) );
       
   158     __ASSERT_ALWAYS( iDataSink, User::Leave( KErrGeneral ) );
       
   159 	
       
   160 	if ( ControlSource( aEndpointId ) )
       
   161 	    {
       
   162 	    __SUBCONTROLLER( "CMccDlDataPath::PauseL, control source" )
       
   163 	    
       
   164 	    SetStateL( EPaused );
       
   165 	    
       
   166 	    iDataSource->SourcePauseL(); 
       
   167 	    }
       
   168 	
       
   169 	if ( ControlSink( aEndpointId ) )
       
   170 	    {
       
   171 	    __SUBCONTROLLER( "CMccDlDataPath::PauseL, control sink" )
       
   172 	    
       
   173 	    if ( IsMmfEndpoint( iAssociatedSink ) )
       
   174 	        {
       
   175 	        __SUBCONTROLLER( "CMccDlDataPath::PauseL, stop mmf sink" )
       
   176 	        
       
   177 	        // Resource has to be freed
       
   178 	        iDataSink->SinkStopL();
       
   179 	        }
       
   180 	    else
       
   181 	        { 
       
   182 	        iDataSink->SinkPauseL(); 
       
   183 	        }
       
   184 	    }
       
   185 	    
       
   186 	if ( State() == EPaused )
       
   187 	    {
       
   188 	    iSourceBuffer = NULL;
       
   189     	
       
   190     	// Cancel the whole path    
       
   191     	Cancel();
       
   192     	
       
   193     	ChangeDataPathTransferState( ECanceled );
       
   194 	    }
       
   195 
       
   196 	__SUBCONTROLLER( "CMccDlDataPath::PauseL, exit" )
       
   197     }
       
   198 
       
   199 // -----------------------------------------------------------------------------
       
   200 // CMccDlDataPath::PlayL
       
   201 // Starts the downlink playing
       
   202 // -----------------------------------------------------------------------------
       
   203 void CMccDlDataPath::PlayL( TUint32 aEndpointId )
       
   204     {
       
   205 	__SUBCONTROLLER( "CMccDlDataPath::PlayL" )
       
   206 	
       
   207 	__ASSERT_ALWAYS( iDataPathCreated, User::Leave( KErrNotReady ) );
       
   208     __ASSERT_ALWAYS( iDataSource, User::Leave( KErrGeneral ) );
       
   209     __ASSERT_ALWAYS( iDataSink, User::Leave( KErrGeneral ) );
       
   210     __ASSERT_ALWAYS( iSourceBuffer, User::Leave( KErrGeneral ) );
       
   211 
       
   212     iDataPathCompletedErrorCode = KErrNone;
       
   213     
       
   214     if ( ControlSource( aEndpointId ) )
       
   215 	    {
       
   216 	    __SUBCONTROLLER( "CMccDlDataPath::PlayL, control source" )
       
   217 	    
       
   218 	    SetStateL( EStreaming );
       
   219       
       
   220         iDataSource->SourcePlayL(); 
       
   221 	    }
       
   222 
       
   223     if ( ControlSink( aEndpointId ) )
       
   224 	    {
       
   225 	    __SUBCONTROLLER( "CMccDlDataPath::PlayL, control sink" )
       
   226 	    
       
   227         iDataSink->SinkPlayL(); 
       
   228 	    }
       
   229 	    
       
   230 	if ( State() == EStreaming && ChangeDataPathTransferState( ENeedSourceData ) )
       
   231 	    {   	
       
   232     	ActivateSourceBuffer();
       
   233 	    }
       
   234 
       
   235 	__SUBCONTROLLER( "CMccDlDataPath::PlayL, exit" )
       
   236     }
       
   237 
       
   238 // -----------------------------------------------------------------------------
       
   239 // CMccDlDataPath::BufferEmptiedL
       
   240 // From MDataSource
       
   241 // ----------------------------------------------------------------------------- 
       
   242 void CMccDlDataPath::BufferEmptiedL( CMMFBuffer* aBuffer )
       
   243     {
       
   244     // This is the buffer returned by DevSound when it has emptied it
       
   245     // Check the buffer that it is not NULL and it is supported.
       
   246     IsBufferSupportedL( aBuffer );
       
   247     if( EStreaming == State() )
       
   248         {
       
   249       	__ASSERT_ALWAYS( aBuffer == iSourceBuffer, User::Leave( KErrArgument ) );
       
   250       	
       
   251 	    iSourceBuffer->SetStatus( EAvailable );
       
   252 	    
       
   253         ChangeDataPathTransferState( ENeedSourceData );
       
   254         }
       
   255     else
       
   256         {
       
   257         // We're not streaming currently, can leave
       
   258         User::Leave( KErrNotReady );
       
   259         }
       
   260     }
       
   261 
       
   262 // -----------------------------------------------------------------------------
       
   263 // CMccDlDataPath::BufferFilledL
       
   264 // From MDataSink
       
   265 // -----------------------------------------------------------------------------
       
   266 void CMccDlDataPath::BufferFilledL( CMMFBuffer* aBuffer )
       
   267     {
       
   268     if( EStreaming == State() )
       
   269         {
       
   270         // There is a leave if aBuffer is NULL
       
   271         // the ownership of the aBuffer is in source, so source
       
   272         // must not give a NULL aBuffer
       
   273         IsBufferSupportedL( aBuffer );
       
   274  
       
   275 	    if ( !aBuffer->BufferSize() /*|| aBuffer->LastBuffer()*/  )
       
   276             {
       
   277             __ASSERT_ALWAYS( iSourceBuffer, User::Leave( KErrArgument ) );
       
   278 
       
   279             // Just in-case we are terminating on BufferSize == 0 or play window
       
   280             iSourceBuffer->SetStatus( EAvailable );  
       
   281             ChangeDataPathTransferState( ENeedSourceData, ETrue );
       
   282             }
       
   283         else
       
   284 	        {
       
   285 		    if( iSourceBuffer != aBuffer )
       
   286 	            {
       
   287 	            // Buffer has been changed by the source
       
   288 	            iSourceBuffer = aBuffer;
       
   289             	}
       
   290             
       
   291             ChangeDataPathTransferState( ESendDataToSink );	
       
   292 	        }
       
   293         }
       
   294     else
       
   295         {
       
   296         // We're not streaming so we can leave
       
   297         User::Leave( KErrNotReady );
       
   298         }
       
   299     }
       
   300 
       
   301 // -----------------------------------------------------------------------------
       
   302 // CMccDlDataPath::FillSourceBufferL
       
   303 // Fill the source buffer
       
   304 // -----------------------------------------------------------------------------
       
   305 void CMccDlDataPath::FillSourceBufferL()
       
   306     {
       
   307     __ASSERT_ALWAYS( iSourceBuffer, User::Leave( KErrNotReady ) );
       
   308     
       
   309     iSourceBuffer->SetStatus( EBeingFilled );
       
   310     iSourceBuffer->SetLastBuffer( EFalse );
       
   311     ChangeDataPathTransferState( EWaitSource );
       
   312     iDataSource->FillBufferL( iSourceBuffer, this, iMediaId );
       
   313     }
       
   314 
       
   315 // -----------------------------------------------------------------------------
       
   316 // CMccDlDataPath::EmptySinkBufferL
       
   317 // Empty the sink buffer
       
   318 // -----------------------------------------------------------------------------
       
   319 void CMccDlDataPath::EmptySinkBufferL()
       
   320     {
       
   321     __ASSERT_ALWAYS( iSourceBuffer, User::Leave( KErrNotReady ) );
       
   322     
       
   323     ChangeDataPathTransferState( EWaitSink );  
       
   324 
       
   325     iSourceBuffer->SetStatus( EFull );
       
   326     TRAPD( error, iDataSink->EmptyBufferL( iSourceBuffer, this, iMediaId ) );
       
   327 
       
   328     if ( KErrEof == error || KErrOverflow == error || KErrUnderflow == error )
       
   329         {
       
   330         iDataPathCompletedErrorCode = error;
       
   331         ChangeDataPathTransferState( EEndOfData );
       
   332         }
       
   333     else
       
   334         {
       
   335         User::LeaveIfError( error );
       
   336         }
       
   337     }
       
   338 
       
   339 // -----------------------------------------------------------------------------
       
   340 // CMccDlDataPath::DoEndOfDataL
       
   341 // Worker function for data ending
       
   342 // -----------------------------------------------------------------------------
       
   343 void CMccDlDataPath::DoEndOfDataL()
       
   344     {
       
   345     if ( KUidMmfAudioOutput != iDataSink->DataSinkType() )
       
   346         {
       
   347         if ( KErrNone == iDataPathCompletedErrorCode )
       
   348             {
       
   349             iDataPathCompletedErrorCode = KErrCompletion;
       
   350             }
       
   351         }
       
   352     
       
   353     SignalDataPathCompleteL(iDataPathCompletedErrorCode);
       
   354 
       
   355     SetStateL( EStopped );
       
   356     }
       
   357 
       
   358 // -----------------------------------------------------------------------------
       
   359 // CMccDlDataPath::Stop
       
   360 // Stop the datapath
       
   361 // -----------------------------------------------------------------------------
       
   362 void CMccDlDataPath::StopL( TUint32 aEndpointId )
       
   363     {
       
   364 	__SUBCONTROLLER( "CMccDlDataPath::StopL" )
       
   365 	
       
   366 	__ASSERT_ALWAYS( iDataPathCreated, User::Leave( KErrNotReady ) );
       
   367 
       
   368     iDataPathCompletedErrorCode = KErrNone;
       
   369     	    
       
   370     if ( ControlSource( aEndpointId ) )
       
   371 	    {
       
   372 	    __SUBCONTROLLER( "CMccDlDataPath::StopL, control source" )
       
   373 	    
       
   374 	    SetStateL( EStopped );
       
   375 	    
       
   376         iDataSource->SourceStopL();
       
   377 	    }
       
   378 	    
       
   379     if ( ControlSink( aEndpointId ) )
       
   380 	    {
       
   381 	    __SUBCONTROLLER( "CMccDlDataPath::StopL, control sink" )
       
   382 	    
       
   383         iDataSink->SinkStopL();
       
   384 	    }
       
   385 	    
       
   386 	if ( State() == EStopped )
       
   387 	    {     	    
       
   388 	    iSourceBuffer = NULL;
       
   389 	
       
   390 	    // Stop the whole path    
       
   391 	    Cancel();
       
   392 	    
       
   393 	    ChangeDataPathTransferState( ECanceled );
       
   394 	    }
       
   395 
       
   396 	__SUBCONTROLLER( "CMccDlDataPath::StopL, exit" )
       
   397     }
       
   398 
       
   399 // -----------------------------------------------------------------------------
       
   400 // CMccDlDataPath::NegotiateL
       
   401 // Negotiate the source and sink
       
   402 // -----------------------------------------------------------------------------
       
   403 void CMccDlDataPath::NegotiateL( MDataSource& aDataSource )
       
   404     {
       
   405     __SUBCONTROLLER( "CMccDlDataPath::NegotiateL" )
       
   406     
       
   407     __ASSERT_ALWAYS( iDataSink, User::Leave( KErrNotReady ) );
       
   408     __ASSERT_ALWAYS( &aDataSource, User::Leave( KErrArgument ) );
       
   409     
       
   410     // NegotiateSourceL will do a re-entry so we need to have iDataSource set
       
   411     // for that call to succeed.
       
   412     iDataSource = &aDataSource;
       
   413     iDataSource->NegotiateSourceL( *iDataSink );
       
   414     iDataSource = NULL;
       
   415     this->AddDataSourceL( &aDataSource );
       
   416     
       
   417     __SUBCONTROLLER( "CMccDlDataPath::NegotiateL exit" )
       
   418     }
       
   419 
       
   420 // -----------------------------------------------------------------------------
       
   421 // CMccDlDataPath::LoadL
       
   422 // -----------------------------------------------------------------------------
       
   423 void CMccDlDataPath::LoadL( MDataSource& aDataSource )
       
   424     {
       
   425     __SUBCONTROLLER( "CMccDlDataPath::LoadL" )
       
   426     
       
   427     __ASSERT_ALWAYS( iDataSink, User::Leave( KErrNotReady ) );
       
   428     iDataSink->NegotiateL( aDataSource );
       
   429     
       
   430     __SUBCONTROLLER( "CMccDlDataPath::LoadL exit" )
       
   431     }
       
   432 
       
   433 // -----------------------------------------------------------------------------
       
   434 // CMccDlDataPath::ResumeL
       
   435 // Resumes pause audio streaming
       
   436 // -----------------------------------------------------------------------------
       
   437 void CMccDlDataPath::ResumeL( TUint32 aEndpointId )
       
   438     {
       
   439 	__SUBCONTROLLER( "CMccDlDataPath::ResumeL" )
       
   440     
       
   441     __ASSERT_ALWAYS( iDataPathCreated, User::Leave( KErrNotReady ) );
       
   442 
       
   443     iDataPathCompletedErrorCode = KErrNone;
       
   444 
       
   445     if ( ControlSource( aEndpointId ) )
       
   446 	    {
       
   447 	    __SUBCONTROLLER( "CMccDlDataPath::ResumeL, control source" )
       
   448 	    
       
   449 	    SetStateL( EStreaming );
       
   450 	    
       
   451         iDataSource->SourcePlayL();
       
   452 	    }
       
   453 	
       
   454 	if ( ControlSink( aEndpointId ) )
       
   455 	    {
       
   456 	    __SUBCONTROLLER( "CMccDlDataPath::ResumeL, control sink" )   
       
   457 	    
       
   458 	    if ( IsMmfEndpoint( iAssociatedSink ) )
       
   459 	        {
       
   460 	        __SUBCONTROLLER( "CMccDlDataPath::ResumeL, prime mmf sink" )
       
   461 	        
       
   462 	        // Resource was freed at pause, initialize it again
       
   463 	        iDataSink->SinkPrimeL();
       
   464 	        }
       
   465 	     
       
   466         iDataSink->SinkPlayL(); 
       
   467 	    }
       
   468 	    
       
   469 	if ( State() == EStreaming && ChangeDataPathTransferState( ENeedSourceData ) )
       
   470 	    {     	    	    
       
   471 	    iSourceBuffer = NULL;
       
   472         TBool bufferReference;
       
   473         iSourceBuffer = 
       
   474             iDataSource->CreateSourceBufferL( iMediaId, bufferReference );
       
   475         __ASSERT_ALWAYS( iSourceBuffer, User::Leave( KErrGeneral ) );
       
   476         __ASSERT_ALWAYS( bufferReference, User::Leave( KErrGeneral ) );
       
   477         	 
       
   478 	    ActivateSourceBuffer();
       
   479 	    }
       
   480 
       
   481 	__SUBCONTROLLER( "CMccDlDataPath::ResumeL, exit" )
       
   482     }
       
   483 
       
   484 // -----------------------------------------------------------------------------
       
   485 // CMccDlDataPath::ActivateSourceBuffer
       
   486 // Sets source buffer available
       
   487 // -----------------------------------------------------------------------------    
       
   488 void CMccDlDataPath::ActivateSourceBuffer()
       
   489     {
       
   490     if ( iSourceBuffer )
       
   491         {
       
   492         iSourceBuffer->SetStatus( EAvailable );
       
   493         }
       
   494     }
       
   495 
       
   496 // ========================== OTHER EXPORTED FUNCTIONS =========================
       
   497 
       
   498 //  End of File