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