williamr@2: // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). williamr@2: // All rights reserved. williamr@2: // This component and the accompanying materials are made available williamr@4: // under the terms of "Eclipse Public License v1.0" williamr@2: // which accompanies this distribution, and is available williamr@4: // at the URL "http://www.eclipse.org/legal/epl-v10.html". williamr@2: // williamr@2: // Initial Contributors: williamr@2: // Nokia Corporation - initial contribution. williamr@2: // williamr@2: // Contributors: williamr@2: // williamr@2: // Description: williamr@2: // source\server\mmfdatapath.h williamr@2: // williamr@2: // williamr@2: williamr@2: #ifndef MMFDATAPATH_H williamr@2: #define MMFDATAPATH_H williamr@2: williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@4: #include williamr@2: williamr@2: /** williamr@2: * @publishedAll williamr@2: * @deprecated williamr@2: * williamr@2: * Datapath general error code used when sending events to clients williamr@2: */ williamr@2: const TUid KMMFErrorCategoryDataPathGeneralError = {0x101F76DC}; williamr@2: williamr@2: williamr@2: williamr@2: /** williamr@2: @publishedAll williamr@2: @deprecated williamr@2: williamr@2: Abstract utility class that moves data from a single data source to a single data sink, via a codec if required. williamr@2: williamr@2: All functions are exported form the DLL and are virtual to allow plugins to define their own data paths. williamr@2: */ williamr@2: class CMMFDataPath : public CActive, williamr@2: public MDataSink, williamr@2: public MDataSource, williamr@2: public MAsyncEventHandler williamr@2: { williamr@2: public: williamr@2: williamr@2: //CMMFDataPath constructor if codec Uid is not already known by CMMFController williamr@2: //and there is no data path ambiguity - ie only one data path is possible williamr@2: IMPORT_C static CMMFDataPath* NewL(MAsyncEventHandler& aEventHandler); williamr@2: williamr@2: //CMMFDataPath constructor if codec Uid is not already known by CMMFController williamr@2: //and there is ambiguity ie more than one possible data path TMediaId used to select path williamr@2: IMPORT_C static CMMFDataPath* NewL(TMediaId aMediaId, MAsyncEventHandler& aEventHandler); williamr@2: williamr@2: //CMMFDataPath constructor if codec Uid is already known by CMMFController williamr@2: //and there is no data path ambiguity - ie only one data path is possible williamr@2: IMPORT_C static CMMFDataPath* NewL(TUid aCodecUid, MAsyncEventHandler& aEventHandler); williamr@2: williamr@2: //CMMFDataPath constructor if codec Uid is already known by CMMFController williamr@2: //and there is ambiguity ie more than one possible data path TMediaId used to select path williamr@2: IMPORT_C static CMMFDataPath* NewL(TUid aCodecUid, TMediaId aMediaId, MAsyncEventHandler& aEventHandler); williamr@2: williamr@2: IMPORT_C virtual ~CMMFDataPath(); williamr@2: williamr@2: // Called when source and sink needs to be de-referenced williamr@2: IMPORT_C virtual void ResetL(); williamr@2: williamr@2: //from MDataSink - CMMFData path is a sink to its MDataSource williamr@2: IMPORT_C virtual void EmptyBufferL(CMMFBuffer* aBuffer, MDataSource* aSupplier, TMediaId aMediaId); //only required for an active push MDataSource requesting a buffer empty - not implemented williamr@2: IMPORT_C virtual void BufferFilledL(CMMFBuffer* aBuffer); //called by the CMMFDataPath's MDataSource when it has filled the buffer williamr@2: IMPORT_C virtual TBool CanCreateSinkBuffer(); //from both MDataSource & MDataSink? williamr@2: IMPORT_C virtual CMMFBuffer* CreateSinkBufferL(TMediaId aMediaId); //CMMFDataPath can't create buffers williamr@2: IMPORT_C virtual CMMFBuffer* CreateSinkBufferL(TMediaId aMediaId, TBool &aReference); //CMMFDataPath can't create buffers williamr@2: williamr@2: IMPORT_C virtual TFourCC SinkDataTypeCode(TMediaId aMediaId); williamr@2: williamr@2: //from MDataSource williamr@2: IMPORT_C virtual void FillBufferL(CMMFBuffer* aBuffer, MDataSink* aConsumer, TMediaId aMediaId); //only required for an active pull MDataSink requesting buffer fill - not implementated williamr@2: IMPORT_C virtual void BufferEmptiedL(CMMFBuffer* aBuffer);//called by the CMMFDataPath's MDataSink when it has emptied the buffer williamr@2: IMPORT_C virtual TBool CanCreateSourceBuffer(); //from both MDataSource & MDataSink? williamr@2: IMPORT_C virtual CMMFBuffer* CreateSourceBufferL(TMediaId aMediaId); //CMMFDataPath can't create buffers williamr@2: IMPORT_C virtual CMMFBuffer* CreateSourceBufferL(TMediaId aMediaId, TBool &aReference); //CMMFDataPath can't create buffers williamr@2: IMPORT_C virtual TFourCC SourceDataTypeCode(TMediaId aMediaId); williamr@2: williamr@2: IMPORT_C virtual void AddDataSourceL(MDataSource* aSource); williamr@2: IMPORT_C virtual void AddDataSinkL(MDataSink* aSink); williamr@2: williamr@2: //could derive these from a mixin eg MMMFControle later for active MDataSource/Sinks williamr@2: IMPORT_C virtual void PrimeL(); williamr@2: IMPORT_C virtual void PlayL(); williamr@2: IMPORT_C virtual void Pause(); williamr@2: IMPORT_C virtual void Stop(); williamr@2: williamr@2: IMPORT_C virtual TTimeIntervalMicroSeconds Position() const; williamr@2: IMPORT_C virtual void SetPositionL(const TTimeIntervalMicroSeconds& aPosition); williamr@2: williamr@2: // Play Window. williamr@2: IMPORT_C virtual void SetPlayWindowL( const TTimeIntervalMicroSeconds& aStart, const TTimeIntervalMicroSeconds& aEnd ) ; williamr@2: IMPORT_C virtual void ClearPlayWindowL() ; williamr@2: williamr@2: //State williamr@2: IMPORT_C virtual TInt State(); williamr@2: williamr@2: //CActive implementations williamr@2: IMPORT_C void RunL(); williamr@2: IMPORT_C void DoCancel(); williamr@2: IMPORT_C TInt RunError(TInt aError); williamr@2: williamr@2: //error handling williamr@2: IMPORT_C TInt DoSendEventToClient(TUid aEventType, TInt aErrorCode); williamr@2: williamr@2: IMPORT_C TInt SetBlockLength(TUint aBlockLength); williamr@2: /** williamr@2: williamr@2: Indicates the state of the data path. williamr@2: williamr@2: Mimics typical MultiMedia behaviour of stopped, primed and playing williamr@2: */ williamr@2: enum TDataPathState williamr@2: { williamr@2: /** Stopped. williamr@2: */ williamr@2: EStopped, williamr@2: /** Primed. williamr@2: */ williamr@2: EPrimed, williamr@2: /** Playing. williamr@2: */ williamr@2: EPlaying, williamr@2: /** Recording. williamr@2: */ williamr@2: ERecording, williamr@2: /** Converting. williamr@2: */ williamr@2: EConverting williamr@2: }; williamr@2: williamr@2: /** williamr@2: @internalComponent williamr@2: */ williamr@2: class CCompleteCallback : public CActive williamr@2: { williamr@2: public: williamr@2: CCompleteCallback(CMMFDataPath& aDataPath, TBool aWaitForSink); williamr@2: ~CCompleteCallback(); williamr@2: williamr@2: void SignalDataPathComplete(TInt aDataPathError); williamr@2: void SignalSinkComplete(TInt aSinkError); williamr@2: TRequestStatus& ActiveStatus(); williamr@2: williamr@2: void DoCancel(); williamr@2: private: williamr@2: void RunL(); williamr@2: CMMFDataPath& iDataPath; williamr@2: TBool iDataPathComplete; williamr@2: TBool iSinkComplete; williamr@2: TBool iWaitForSink; williamr@2: williamr@2: TInt iSinkError; williamr@2: TInt iDataPathError; williamr@2: }; williamr@2: friend class CCompleteCallback; williamr@2: friend class CMMFDataPath2; williamr@2: protected: williamr@2: williamr@2: /** williamr@2: Indicates the transfer state. williamr@2: williamr@2: Buffers maybe be filled, emptied, or have "one" shot initialisatings performed upon them. williamr@2: williamr@2: TTransferState is used within the datapath RunL which drives databuffer exchange. williamr@2: */ williamr@2: enum TTransferState williamr@2: { williamr@2: /** Waiting on a BufferEmptied callback from sink williamr@2: */ williamr@2: EWaitSink, williamr@2: /** Waiting on a BufferFilled callback from source williamr@2: */ williamr@2: EWaitSource, williamr@2: /** Initialize the sink. williamr@2: */ williamr@2: EInitializeSink, williamr@2: /** Initialize the source. williamr@2: */ williamr@2: EInitializeSource, williamr@2: /** Source buffer does not contain data. williamr@2: */ williamr@2: ENeedSourceData, williamr@2: /** Sink buffer does not contain data. williamr@2: */ williamr@2: ENeedSinkData, williamr@2: /** There is more source data to send to the sink and need to match sink and source. williamr@2: */ williamr@2: ENeedToMatchSourceToSink, williamr@2: /** Outstanding data to send to sink. williamr@2: */ williamr@2: ESendDataToSink, williamr@2: /** End of data. williamr@2: */ williamr@2: EEndOfData //indicates that the datapath has transferred all the data to the sink williamr@2: }; williamr@2: williamr@2: williamr@2: williamr@2: williamr@2: protected: williamr@2: CMMFDataPath(TMediaId aMediaId, MAsyncEventHandler& aEventHandler) : williamr@2: CActive(EPriorityStandard), MDataSink(KUidMmfDataPath), MDataSource(KUidMmfDataPath), williamr@2: iEventHandler(aEventHandler), iMediaId(aMediaId), iState(EStopped) williamr@2: {CActiveScheduler::Add(this);}; williamr@2: williamr@2: IMPORT_C void ConstructL(TUid aCodecUid = KNullUid); williamr@2: IMPORT_C virtual void ConstructSourceL( const TDesC8& aInitData ) ; williamr@2: IMPORT_C virtual void ConstructSinkL( const TDesC8& aInitData ) ; williamr@2: IMPORT_C virtual void EndOfData(); williamr@2: williamr@2: //These methods use API on DevSound to determine how many samples have been played/recorded williamr@2: //and thereby determine the real position. williamr@2: TTimeIntervalMicroSeconds CalculateAudioOutputPosition() const; williamr@2: TTimeIntervalMicroSeconds CalculateAudioInputPosition() const; williamr@2: williamr@2: //These methods determine the position of either the input or the output. williamr@2: //The position may come from a format or from an audio input/output depending on williamr@2: //the operation the datapath is doing (Playing (output), Recording & Converting (input)) williamr@2: TTimeIntervalMicroSeconds OutputPosition() const; williamr@2: TTimeIntervalMicroSeconds InputPosition() const; williamr@2: williamr@2: williamr@2: //Determines what buffers are required (see TNeedBuffer) williamr@2: //May leave KErrNotSupported if source/sinks can't supply the necessary buffers williamr@2: TInt DetermineBuffersToUseL(void) const; williamr@2: williamr@2: //Determines how many samples have been played by DevSound williamr@2: TInt AudioSamplesPlayed() const; williamr@2: williamr@2: //Determines how many samples have been recorded by DevSound williamr@2: TInt AudioSamplesRecorded() const; williamr@2: williamr@2: williamr@2: private: williamr@2: void ChangeDataPathTransferState(TTransferState aNewDataPathTransferState); williamr@2: void CreateDataPathL(MDataSource* aSource, MDataSink* aSink); williamr@2: williamr@2: void InitializeSinkL(); williamr@2: void InitializeSourceL(); williamr@2: void FillSourceBufferL(); williamr@2: void FillSinkBufferL(); williamr@2: void EmptySinkBufferL(); williamr@2: void DoCleanupBuffers(); williamr@2: void ObtainSyncBuffersL(); //tries to obtain synchronous data buffers from src/snk williamr@2: williamr@2: TTimeIntervalMicroSeconds Duration() const; williamr@2: williamr@2: void DoStopL(); williamr@2: void DoPauseL(); williamr@2: void DoEndOfDataL(); williamr@2: williamr@2: IMPORT_C TInt SendEventToClient(const TMMFEvent& aEvent); williamr@2: williamr@2: void SetBuffersAvailable(); williamr@2: void ResetRefBuffers(); williamr@2: williamr@2: williamr@2: williamr@2: protected: williamr@2: /** williamr@2: Event handler. williamr@2: */ williamr@2: MAsyncEventHandler& iEventHandler; williamr@2: williamr@2: /** williamr@2: The source of data to which the CMMFDataPath is a MDataSink for. williamr@2: */ williamr@2: MDataSource* iDataSource; williamr@2: /** williamr@2: The sink of data for which the CMMFDataPath is a MDataSource for williamr@2: */ williamr@2: MDataSink* iDataSink; williamr@2: /** williamr@2: Set to true when the sink is able to accept data. EFalse otherwise. williamr@2: */ williamr@2: TBool iSinkCanReceive; williamr@2: /** williamr@2: The sink's data type. Same as the codec input data type. williamr@2: */ williamr@2: TFourCC iSinkFourCC; williamr@2: /** williamr@2: The source's data type. Same as the codec output data type. williamr@2: */ williamr@2: TFourCC iSourceFourCC; williamr@2: /** williamr@2: Identifies which media type and stream within MDataSource. williamr@2: */ williamr@2: TMediaId iMediaId; williamr@2: /** williamr@2: Codec in use. Null Codec is signified by == NULL williamr@2: */ williamr@2: CMMFCodec* iCodec; williamr@2: williamr@2: /** williamr@2: Result of processing the codec. williamr@2: */ williamr@2: TCodecProcessResult iCodecProcessResult; williamr@2: williamr@2: /** williamr@2: Set to ETrue when the data path has a source and a sink and can send data from the source to the sink. williamr@2: */ williamr@2: TBool iDataPathCreated; williamr@2: williamr@2: /** williamr@2: Current data path state. williamr@2: @see TDataPathState williamr@2: */ williamr@2: TDataPathState iState; williamr@2: williamr@2: /** williamr@2: Current transfer state. williamr@2: @see TTransferState williamr@2: */ williamr@2: TTransferState iTransferState; williamr@2: williamr@2: /** williamr@2: Set to true if data path has to use a supplied codec in its construction. williamr@2: */ williamr@2: TBool iUseSuppliedCodecUid; williamr@2: williamr@2: /** williamr@2: This is set to point to whichever sink buffer is in use. williamr@2: */ williamr@2: CMMFBuffer* iSinkBuffer; williamr@2: williamr@2: /** williamr@2: This is the pointer to whichever source buffer is in use williamr@2: */ williamr@2: CMMFBuffer* iSourceBuffer; williamr@2: williamr@2: /** williamr@2: The source's position in terms of frames or some other time fixed parameter. williamr@2: */ williamr@2: TUint iCurrentSourceFrameNumber; williamr@2: williamr@2: /** williamr@2: The sink's position in terms of frames or some other time fixed parameter. williamr@2: */ williamr@2: TUint iCurrentSinkFrameNumber; williamr@2: williamr@2: /** williamr@2: Indicates that all data has been obtained from the source (ETrue if there is no more source data). williamr@2: */ williamr@2: TBool iNoMoreSourceData; williamr@2: williamr@2: /** williamr@2: Indicates that all data has been sent to the sink. williamr@2: */ williamr@2: TBool iAllDataSentToSink; williamr@2: williamr@2: /** williamr@2: Datapath completed because of an error; usually KErrNone. williamr@2: */ williamr@2: TUint iDataPathCompletedErrorCode; williamr@2: williamr@2: /** williamr@2: Start position of the play window. williamr@2: */ williamr@2: TTimeIntervalMicroSeconds iPlayWindowStartPosition ; williamr@2: williamr@2: /** williamr@2: End position of the play window. williamr@2: */ williamr@2: TTimeIntervalMicroSeconds iPlayWindowEndPosition ; williamr@2: williamr@2: /** williamr@2: The position audio will start playing from. williamr@2: When stopping, this is set to iPlayWindowStartPosition. williamr@2: When pausing, this is set to the current position. williamr@2: */ williamr@2: TTimeIntervalMicroSeconds iStartPosition; williamr@2: williamr@2: /** williamr@2: This value can be used to obtain the duration of the source when playing or converting. williamr@2: This is an optimisation as this value will not change if we are playing or converting. williamr@2: */ williamr@2: TTimeIntervalMicroSeconds iCachedSourceDuration; williamr@2: williamr@2: williamr@2: /** williamr@2: ETrue if the source buffer is reference to object owned by someone else. williamr@2: */ williamr@2: TBool iSrcBufRef; williamr@2: williamr@2: /** williamr@2: ETrue if sink buffer is reference to object owned by someone else williamr@2: */ williamr@2: TBool iSnkBufRef; williamr@2: williamr@2: /** williamr@2: Indicates asynchrous buffers from AudioInput. williamr@2: */ williamr@2: TBool iObtainingAsyncSourceBuffer; williamr@2: williamr@2: /** williamr@2: Indicates asynchrous buffers from AudioOutput. williamr@2: */ williamr@2: TBool iObtainingAsyncSinkBuffer; williamr@2: williamr@2: /** williamr@2: Indicates DoPauseL() has been called. williamr@2: */ williamr@2: TBool iPauseCalled; williamr@2: williamr@2: /** williamr@2: Flag to indicate that a buffer is with the source. williamr@2: williamr@2: This is necessary as it is imperrative that when a buffer is with the source, it must williamr@2: not be referenced in any way. The reason for this is that it is not mandated that sources williamr@2: maintain buffer references. For example, it is valid for DevSound to return recorded data in a williamr@2: different buffer to the one supplied to it. williamr@2: */ williamr@2: TBool iSourceBufferWithSource; williamr@2: williamr@2: /** williamr@2: Flag to indicate that a buffer is with the sink. williamr@2: williamr@2: This are necessary as it is imperrative that when a buffer is with the sink, it must williamr@2: not be referenced in any way. The reason for this is that it is not mandated that sinks williamr@2: maintain buffer references. For example, it is valid for DevSound to request more audio data in a williamr@2: different buffer to the one supplied to it. williamr@2: */ williamr@2: TBool iSinkBufferWithSink; williamr@2: williamr@2: williamr@2: /** williamr@2: Holds the number of samples played on audio output at a point where we williamr@2: want to reference play duration from. williamr@2: */ williamr@2: TInt iReferenceAudioSamplesPlayed; williamr@2: williamr@2: /** williamr@2: Holds the number of samples recorded from audio input at a point where we williamr@2: want to reference record duration from. williamr@2: */ williamr@2: TInt iReferenceAudioSamplesRecorded; williamr@2: williamr@2: /** williamr@2: Pointer to internal callback completion class williamr@2: */ williamr@2: CCompleteCallback * iCompleteCallback; williamr@2: williamr@2: /** williamr@2: This indicates what buffers are required in order to operate. williamr@2: If a real Codec is in use, buffers are required from both source and sink, williamr@2: else only one is required and source is preferred. williamr@2: */ williamr@2: enum TNeedBuffer williamr@2: { williamr@2: /** No buffers needed. williamr@2: */ williamr@2: ENoBuffers = 0x0, williamr@2: /** Sink buffer needed. williamr@2: */ williamr@2: ENeedSinkBuffer = 0x01, williamr@2: /** Source buffer needed. williamr@2: */ williamr@2: ENeedSourceBuffer = 0x10 williamr@2: }; williamr@2: williamr@2: /** Holds the outcome of the call to DetermineBuffersToUseL williamr@2: */ williamr@2: TInt iBuffersToUse; williamr@2: }; williamr@2: williamr@2: #endif williamr@4: