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