sl@0: // Copyright (c) 2002-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: // Audio, MIDI and Video client utility functions. sl@0: // sl@0: // sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: using namespace ContentAccess; sl@0: sl@0: #include "mmfclientutility.h" sl@0: #include sl@0: sl@0: const TInt KMaxMimeLength = 256; sl@0: const TInt KMaxHeaderSize = 256; sl@0: const TInt KExpandSize = 100; sl@0: sl@0: #ifdef SYMBIAN_ENABLE_MMF_MULTISCREEN_SUPPORT sl@0: const TInt KDefaultScreenNo = 0; sl@0: #endif sl@0: sl@0: void CUPanic(TInt aCUPanicCode) sl@0: { sl@0: _LIT(KMMFMediaClientUtilityPaanicCategory, "MMFClientUtility"); sl@0: User::Panic(KMMFMediaClientUtilityPaanicCategory, aCUPanicCode); sl@0: } sl@0: sl@0: /** sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C TUid CMMFClientUtility::ConvertMdaFormatUidToECOMWrite(TUid aMdaFormatUid) sl@0: { sl@0: TUid ECOMUid = KNullUid; sl@0: if (aMdaFormatUid == KUidMdaClipFormatWav) sl@0: ECOMUid = TUid::Uid(KMmfUidFormatWAVWrite); sl@0: else if (aMdaFormatUid == KUidMdaClipFormatAu) sl@0: ECOMUid = TUid::Uid(KMmfUidFormatAUWrite); sl@0: else if (aMdaFormatUid == KUidMdaClipFormatRawAudio) sl@0: ECOMUid = TUid::Uid(KMmfUidFormatRAWWrite); sl@0: else if (aMdaFormatUid == KUidMdaClipFormatRawAmr) sl@0: ECOMUid = TUid::Uid(KAdvancedUidFormatAMRWrite); sl@0: sl@0: return ECOMUid; sl@0: } sl@0: sl@0: /** sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C TUid CMMFClientUtility::ConvertMdaFormatUidToECOMRead(TUid aMdaFormatUid) sl@0: { sl@0: TUid ECOMUid = KNullUid; sl@0: if (aMdaFormatUid == KUidMdaClipFormatWav) sl@0: ECOMUid = TUid::Uid(KMmfUidFormatWAVRead); sl@0: else if (aMdaFormatUid == KUidMdaClipFormatAu) sl@0: ECOMUid = TUid::Uid(KMmfUidFormatAURead); sl@0: else if (aMdaFormatUid == KUidMdaClipFormatRawAudio) sl@0: ECOMUid = TUid::Uid(KMmfUidFormatRAWRead); sl@0: else if (aMdaFormatUid == KUidMdaClipFormatRawAmr) sl@0: ECOMUid = TUid::Uid(KAdvancedUidFormatAMRRead); sl@0: sl@0: return ECOMUid; sl@0: } sl@0: sl@0: /** sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C TInt CMMFClientUtility::GetFileHeaderData(const TDesC& aFileName, TDes8& aHeaderData, TInt aMaxLength) sl@0: { sl@0: RFs fsSession; sl@0: RFile file; sl@0: TInt error = KErrNone; sl@0: sl@0: if ((error = fsSession.Connect()) == KErrNone) sl@0: { sl@0: if ((error = file.Open(fsSession, aFileName, EFileShareReadersOrWriters)) == KErrNone) sl@0: { sl@0: TInt size = 0; sl@0: sl@0: if ((error = file.Size(size)) == KErrNone) sl@0: { sl@0: if (size > 0) sl@0: { sl@0: if (size > aMaxLength) sl@0: size = aMaxLength; sl@0: sl@0: error = file.Read(aHeaderData, size); sl@0: } sl@0: } sl@0: file.Close(); sl@0: } sl@0: fsSession.Close(); sl@0: } sl@0: sl@0: return error; sl@0: } sl@0: sl@0: /** sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C TFourCC CMMFClientUtility::ConvertMdaCodecToFourCC(TMdaPackage& aCodec) sl@0: { sl@0: TFourCC dataType = KMMFFourCCCodeNULL; sl@0: switch (aCodec.Uid().iUid) sl@0: { sl@0: case KUidMdaWavPcmCodecDefine: sl@0: { sl@0: TMdaPcmWavCodec* pcmWavCodec = (TMdaPcmWavCodec*)&aCodec; sl@0: if (pcmWavCodec->iBits == TMdaPcmWavCodec::E8BitPcm) sl@0: dataType = KMMFFourCCCodePCMU8; //8 bit PCM sl@0: else sl@0: dataType = KMMFFourCCCodePCM16; //16 bit PCM sl@0: break; sl@0: } sl@0: case KUidMdaAu8PcmCodecDefine: sl@0: dataType = KMMFFourCCCodePCM8; sl@0: break; sl@0: case KUidMdaAuCodecDefine: sl@0: case KUidMdaAu16PcmCodecDefine: sl@0: dataType = KMMFFourCCCodePCM16B; sl@0: break; sl@0: sl@0: case KUidMdaAuMulawCodecDefine: sl@0: case KUidMdaWavMulawCodecDefine: sl@0: case KUidMdaRawAudioMulawCodecDefine: //uLAW sl@0: dataType = KMMFFourCCCodeMuLAW; sl@0: break; sl@0: case KUidMdaAuAlawCodecDefine: sl@0: case KUidMdaWavAlawCodecDefine: sl@0: case KUidMdaRawAudioAlawCodecDefine: //ALAW sl@0: dataType = KMMFFourCCCodeALAW; sl@0: break; sl@0: case KUidMdaRawAudioS8PcmCodecDefine: // P8 sl@0: dataType = KMMFFourCCCodePCM8; sl@0: break; sl@0: case KUidMdaRawAudioU8PcmCodecDefine: // PU8 sl@0: dataType = KMMFFourCCCodePCMU8; sl@0: break; sl@0: case KUidMdaRawAudioSL16PcmCodecDefine: // P16 sl@0: dataType = KMMFFourCCCodePCM16; sl@0: break; sl@0: case KUidMdaRawAudioSB16PcmCodecDefine: //P16B sl@0: dataType = KMMFFourCCCodePCM16B; sl@0: break; sl@0: case KUidMdaRawAudioUL16PcmCodecDefine: //PU16 sl@0: dataType = KMMFFourCCCodePCMU16; sl@0: break; sl@0: case KUidMdaRawAudioUB16PcmCodecDefine: //PU6B sl@0: dataType = KMMFFourCCCodePCMU16B; sl@0: break; sl@0: case KUidMdaGsmWavCodecDefine: //GSM6 sl@0: dataType = KMMFFourCCCodeGSM610; sl@0: break; sl@0: case KUidMdaWavImaAdpcmCodecDefine: sl@0: dataType = KMMFFourCCCodeIMAD; sl@0: break; sl@0: case KUidMdaRawAmrCodecDefine: sl@0: dataType = KMMFFourCCCodeAMR; sl@0: break; sl@0: default: // Not a Uid we recognise sl@0: dataType = KMMFFourCCCodeNULL; sl@0: break; sl@0: } sl@0: return dataType; sl@0: } sl@0: sl@0: sl@0: CMMFUtilityFileInfo* CMMFUtilityFileInfo::NewL(TMMSource& aSource, TBool aSecureDRMMode) sl@0: { sl@0: CMMFUtilityFileInfo* self = CMMFUtilityFileInfo::NewLC(aSource, aSecureDRMMode); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: sl@0: CMMFUtilityFileInfo* CMMFUtilityFileInfo::NewLC(TMMSource& aSource, TBool aSecureDRMMode) sl@0: { sl@0: CMMFUtilityFileInfo* self = new (ELeave) CMMFUtilityFileInfo; sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aSource, aSecureDRMMode); sl@0: return self; sl@0: } sl@0: sl@0: sl@0: void CMMFUtilityFileInfo::ConstructL(const TMMSource& aSource, TBool aSecureDRMMode) sl@0: { sl@0: if (!aSecureDRMMode) sl@0: { sl@0: if (aSource.SourceType()==KUidMMFileSource) sl@0: { sl@0: const TMMFileSource& fileSource = static_cast(aSource); sl@0: iData = CData::NewL(TVirtualPathPtr(fileSource.Name(), fileSource.UniqueId()), sl@0: EContentShareReadWrite); sl@0: } sl@0: sl@0: if (aSource.SourceType()==KUidMMFileHandleSource) sl@0: { sl@0: const TMMFileHandleSource& fileHandleSource = static_cast(aSource); sl@0: iData = CData::NewL(fileHandleSource.Handle(), fileHandleSource.UniqueId()); sl@0: } sl@0: sl@0: TInt err = iData->SetProperty(EAgentPropertyAgentUI, aSource.IsUIEnabled()); sl@0: if (err != KErrNone && err != KErrCANotSupported) sl@0: { sl@0: // KErrCANotSupported isn't a problem for us so eat the error code. sl@0: User::Leave(err); sl@0: } sl@0: sl@0: err = iData->EvaluateIntent(aSource.Intent()); sl@0: User::LeaveIfError(err); sl@0: } sl@0: else sl@0: { sl@0: // Use RMMFDRMPluginServerProxy as medium sl@0: iDrmPluginServer = new (ELeave) RMMFDRMPluginServerProxy; sl@0: User::LeaveIfError(iDrmPluginServer->Open()); sl@0: sl@0: CBufFlat* dataBuffer = CBufFlat::NewL(KExpandSize); sl@0: CleanupStack::PushL(dataBuffer); sl@0: RBufWriteStream stream; sl@0: stream.Open(*dataBuffer); sl@0: CleanupClosePushL(stream); sl@0: sl@0: stream.WriteInt32L(aSource.UniqueId().Length()); sl@0: stream.WriteL(aSource.UniqueId()); sl@0: stream.WriteInt32L(aSource.IsUIEnabled()); sl@0: TPckgBuf intentPckg(aSource.Intent()); sl@0: stream.WriteL(intentPckg); sl@0: stream.CommitL(); sl@0: sl@0: CleanupStack::PopAndDestroy(&stream); sl@0: if (aSource.SourceType()==KUidMMFileSource) sl@0: { sl@0: const TMMFileSource& fileSource = static_cast(aSource); sl@0: iDrmPluginServer->OpenDataContentL(fileSource.Name(), dataBuffer->Ptr(0)); sl@0: } sl@0: if (aSource.SourceType()==KUidMMFileHandleSource) sl@0: { sl@0: const TMMFileHandleSource& fileHandleSource = static_cast(aSource); sl@0: iDrmPluginServer->OpenDataContentL(fileHandleSource.Handle(), dataBuffer->Ptr(0)); sl@0: } sl@0: CleanupStack::PopAndDestroy(dataBuffer); sl@0: } sl@0: } sl@0: sl@0: TInt CMMFUtilityFileInfo::EvaluateIntent(TIntent aIntent) sl@0: { sl@0: if (iData) sl@0: { sl@0: return iData->EvaluateIntent(aIntent); sl@0: } sl@0: else sl@0: { sl@0: ASSERT(iDrmPluginServer); sl@0: return iDrmPluginServer->EvaluateDataContentIntent(aIntent); sl@0: } sl@0: } sl@0: /** sl@0: * @internalComponent sl@0: */ sl@0: TBool CMMFUtilityFileInfo::GetFileMimeTypeL(TDes8& aMimeType) sl@0: { sl@0: if (iData) sl@0: { sl@0: return iData->GetMimeTypeL(aMimeType); sl@0: } sl@0: else sl@0: { sl@0: ASSERT(iDrmPluginServer); sl@0: return iDrmPluginServer->GetDataContentMimeTypeL(aMimeType); sl@0: } sl@0: } sl@0: sl@0: /** sl@0: * @internalComponent sl@0: */ sl@0: void CMMFUtilityFileInfo::GetFileHeaderDataL(TDes8& aHeaderData, TInt aMaxLength) sl@0: { sl@0: if (iData) sl@0: { sl@0: TInt size = 0; sl@0: iData->DataSizeL(size); sl@0: if (size > 0) sl@0: { sl@0: if (size > aMaxLength) sl@0: size = aMaxLength; sl@0: TInt pos = 0; sl@0: User::LeaveIfError(iData->Seek(ESeekStart, pos)); sl@0: User::LeaveIfError(iData->Read(aHeaderData, size)); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: ASSERT(iDrmPluginServer); sl@0: iDrmPluginServer->GetDataContentFileHeaderL(aHeaderData, aMaxLength); sl@0: } sl@0: } sl@0: sl@0: /** sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C HBufC8* CMMFClientUtility::GetFileExtensionL(const TDesC& aFileName) sl@0: { sl@0: TParse fileName; sl@0: fileName.Set(aFileName,NULL,NULL); sl@0: HBufC8* fileSuffix = NULL; sl@0: if(fileName.ExtPresent()) sl@0: { sl@0: TPtrC fileSuffixPtr(fileName.Ext()); sl@0: fileSuffix = HBufC8::NewL(fileSuffixPtr.Length()); sl@0: fileSuffix->Des().Copy(fileSuffixPtr); sl@0: } sl@0: else sl@0: { sl@0: fileSuffix = KNullDesC8().AllocL(); sl@0: } sl@0: return fileSuffix; sl@0: } sl@0: sl@0: sl@0: /** sl@0: * @internalComponent sl@0: */ sl@0: CMMFUtilityFileInfo::~CMMFUtilityFileInfo() sl@0: { sl@0: if (iData) sl@0: { sl@0: delete iData; sl@0: } sl@0: if (iDrmPluginServer) sl@0: { sl@0: iDrmPluginServer->Close(); sl@0: delete iDrmPluginServer; sl@0: } sl@0: } sl@0: sl@0: /* sl@0: * @internalComponent sl@0: * sl@0: * Returns an integer rating indicating how well the supplied format matches sl@0: * the header data and file extension supplied. sl@0: * 3 brownie points awarded for data & suffix match. sl@0: * 2 brownie points awarded for data match alone. sl@0: * 1 brownie point awarded for suffix match alone. sl@0: */ sl@0: TInt CMMFClientUtility::GetBestMatchL(const CMMFFormatImplementationInformation* format, const TDesC8& aHeaderData, const TDesC8& aFileExtension) sl@0: { sl@0: TInt browniePoints = 0; sl@0: sl@0: if (aHeaderData.Length() > 0) // Non empty file sl@0: { sl@0: if (aFileExtension.Length() > 0) // With a file extension sl@0: { sl@0: if (format->SupportsHeaderDataL(aHeaderData) && sl@0: format->SupportsFileExtension(aFileExtension)) sl@0: { sl@0: browniePoints = 3; sl@0: } sl@0: else if (format->SupportsHeaderDataL(aHeaderData)) sl@0: { sl@0: browniePoints = 2; sl@0: } sl@0: else sl@0: { sl@0: // See if this format has any 'empty' match data or no match data, indicating sl@0: // that this format will match extension alone even if data present. sl@0: // (A format may have more than one match data string.) sl@0: const CDesC8Array& supportedHeaderData = format->SupportedHeaderData(); sl@0: sl@0: if (supportedHeaderData.Count() == 0) sl@0: { sl@0: // No header data indicated. sl@0: if (format->SupportsFileExtension(aFileExtension)) sl@0: { sl@0: browniePoints = 1; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: for (register TInt i = 0; i < supportedHeaderData.Count(); i++) sl@0: { sl@0: if ((supportedHeaderData[i].Length() == 0) && sl@0: format->SupportsFileExtension(aFileExtension)) sl@0: { sl@0: browniePoints = 1; sl@0: } sl@0: } sl@0: } sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // No file suffix, so must match header data alone. sl@0: if (format->SupportsHeaderDataL(aHeaderData)) sl@0: { sl@0: browniePoints = 2; sl@0: } sl@0: } sl@0: } sl@0: else // Empty File sl@0: { sl@0: // We have no choice but to match extension, if there is one. sl@0: if ((aFileExtension.Length() > 0) && format->SupportsFileExtension(aFileExtension)) sl@0: { sl@0: browniePoints = 1; sl@0: } sl@0: } sl@0: sl@0: return browniePoints; sl@0: } sl@0: sl@0: /** sl@0: * @internalComponent sl@0: * sl@0: * This function parses all the play & record formats in the given list of controllers, sl@0: * looking for controllers & formats that best match the requirements. sl@0: * Play controllers will be returned before record controllers, and sl@0: * in cases of equal priority between formats, ECom order will be maintained. sl@0: * sl@0: * @param "aControllers" sl@0: * A reference to a user supplied list of controllers retrieved from ECom. sl@0: * This list may be have been filtered for audio/video/play/record. sl@0: * @param "aHeaderDataPlayback" sl@0: * A descriptor reference containing the file's header data. sl@0: * for matching against a controller's play formats. May be KNullDesC8 sl@0: * @param "aFileExtensionPlayback" sl@0: * A descriptor reference containing the filename's extension. sl@0: * for matching against a controller's play formats. May be KNullDesC8 sl@0: * @param "aHeaderDataRecord" sl@0: * A descriptor reference containing the file's header data. sl@0: * for matching against a controller's record formats. May be KNullDesC8 sl@0: * @param "aFileExtensionRecord" sl@0: * A descriptor reference containing the filename's extension. sl@0: * for matching against a controller's record formats. May be KNullDesC8 sl@0: * @param "aPrioritisedControllers" sl@0: * A reference to a user supplied list through which the list of sl@0: * prioritised controllers will be returned. sl@0: * @since 7.0s sl@0: */ sl@0: void CMMFClientUtility::PrioritiseControllersL( sl@0: const RMMFControllerImplInfoArray& aControllers, sl@0: const TDesC8& aHeaderDataPlayback, sl@0: const TDesC8& aFileExtensionPlayback, sl@0: const TDesC8& aHeaderDataRecord, sl@0: const TDesC8& aFileExtensionRecord, sl@0: RMMFControllerImplInfoArray& prioritisedControllers) sl@0: { sl@0: RMMFControllerImplInfoArray fullMatchControllers; // data AND suffix sl@0: CleanupClosePushL(fullMatchControllers); sl@0: RMMFControllerImplInfoArray partMatchControllers; // data OR suffix sl@0: CleanupClosePushL(partMatchControllers); sl@0: sl@0: TBool checkingPlaybackFormats = EFalse; sl@0: TBool checkingRecordFormats = EFalse; sl@0: sl@0: if (aHeaderDataPlayback != KNullDesC8 || aFileExtensionPlayback != KNullDesC8) sl@0: checkingPlaybackFormats = ETrue; sl@0: if (aHeaderDataRecord != KNullDesC8 || aFileExtensionRecord != KNullDesC8) sl@0: checkingRecordFormats = ETrue; sl@0: sl@0: // Examine each format for each controller. We only want to know at this stage sl@0: // if the controller has suitable formats, so as soon as we know it has, we can sl@0: // add it to out list, ranked by how well it matched. sl@0: for (register TInt i = 0; i < aControllers.Count(); i++) sl@0: { sl@0: const CMMFControllerImplementationInformation* controller = aControllers[i]; sl@0: TInt savedBrowniePointsPlayback = 0; sl@0: TInt savedBrowniePointsRecord = 0; sl@0: sl@0: if (checkingPlaybackFormats) sl@0: { sl@0: for (register TInt p = 0; p < controller->PlayFormats().Count(); p++) sl@0: { sl@0: const CMMFFormatImplementationInformation* format = controller->PlayFormats()[p]; sl@0: sl@0: TInt browniePoints = GetBestMatchL(format, aHeaderDataPlayback, aFileExtensionPlayback); sl@0: sl@0: if (browniePoints >= savedBrowniePointsPlayback) sl@0: savedBrowniePointsPlayback = browniePoints; sl@0: } sl@0: } sl@0: sl@0: if (checkingRecordFormats) sl@0: { sl@0: for (register TInt r = 0; r < controller->RecordFormats().Count(); r++) sl@0: { sl@0: const CMMFFormatImplementationInformation* format = controller->RecordFormats()[r]; sl@0: sl@0: TInt browniePoints = GetBestMatchL(format, aHeaderDataRecord, aFileExtensionRecord); sl@0: sl@0: if (browniePoints >= savedBrowniePointsRecord) sl@0: savedBrowniePointsRecord = browniePoints; sl@0: } sl@0: } sl@0: sl@0: TInt savedBrowniePoints = 0; sl@0: // if we're checking both playback & record formats sl@0: // make sure we've found both sl@0: if (checkingPlaybackFormats && checkingRecordFormats) sl@0: { sl@0: savedBrowniePoints = Min(savedBrowniePointsPlayback, savedBrowniePointsRecord); sl@0: } sl@0: else if (checkingPlaybackFormats) sl@0: { sl@0: savedBrowniePoints = savedBrowniePointsPlayback; sl@0: } sl@0: else if (checkingRecordFormats) sl@0: { sl@0: savedBrowniePoints = savedBrowniePointsRecord; sl@0: } sl@0: sl@0: // Checked all formats for this controller, now count our brownie points. sl@0: switch (savedBrowniePoints) sl@0: { sl@0: case 3: sl@0: User::LeaveIfError(fullMatchControllers.Append(controller)); sl@0: break; sl@0: case 2: sl@0: User::LeaveIfError(partMatchControllers.Insert(controller, 0)); sl@0: break; sl@0: case 1: sl@0: User::LeaveIfError(partMatchControllers.Append(controller)); sl@0: break; sl@0: default: sl@0: break; sl@0: } sl@0: } sl@0: sl@0: // The better the controller matches, the earlier it will be in the final list. sl@0: for (register TInt x = 0; x < fullMatchControllers.Count(); x++) sl@0: { sl@0: if (prioritisedControllers.Find(fullMatchControllers[x]) == KErrNotFound) sl@0: { sl@0: User::LeaveIfError(prioritisedControllers.Append(fullMatchControllers[x])); sl@0: } sl@0: } sl@0: sl@0: for (register TInt y = 0; y < partMatchControllers.Count(); y++) sl@0: { sl@0: if (prioritisedControllers.Find(partMatchControllers[y]) == KErrNotFound) sl@0: { sl@0: User::LeaveIfError(prioritisedControllers.Append(partMatchControllers[y])); sl@0: } sl@0: } sl@0: sl@0: CleanupStack::PopAndDestroy(2, &fullMatchControllers); // fullMatchControllers, partMatchControllers sl@0: } sl@0: sl@0: /** sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C CMMFMdaObjectStateChangeObserverCallback* CMMFMdaObjectStateChangeObserverCallback::NewL(MMdaObjectStateChangeObserver& aCallback) sl@0: { sl@0: return new(ELeave) CMMFMdaObjectStateChangeObserverCallback(aCallback); sl@0: } sl@0: sl@0: /** sl@0: * @internalComponent sl@0: */ sl@0: CMMFMdaObjectStateChangeObserverCallback::~CMMFMdaObjectStateChangeObserverCallback() sl@0: { sl@0: Cancel(); sl@0: } sl@0: sl@0: /** sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C void CMMFMdaObjectStateChangeObserverCallback::CallBack(CBase* aObject, TInt aPreviousState, TInt aCurrentState, TInt aErrorCode) sl@0: { sl@0: iObject = aObject; sl@0: iPreviousState = aPreviousState; sl@0: iCurrentState = aCurrentState; sl@0: iErrorCode = aErrorCode; sl@0: if (!IsActive()) sl@0: { sl@0: TRequestStatus* s = &iStatus; sl@0: SetActive(); sl@0: User::RequestComplete(s, KErrNone); sl@0: } sl@0: } sl@0: sl@0: CMMFMdaObjectStateChangeObserverCallback::CMMFMdaObjectStateChangeObserverCallback(MMdaObjectStateChangeObserver& aCallback) : sl@0: CActive(CActive::EPriorityHigh), sl@0: iCallback(aCallback) sl@0: { sl@0: CActiveScheduler::Add(this); sl@0: } sl@0: sl@0: void CMMFMdaObjectStateChangeObserverCallback::RunL() sl@0: { sl@0: iCallback.MoscoStateChangeEvent(iObject, iPreviousState, iCurrentState, iErrorCode); sl@0: } sl@0: sl@0: void CMMFMdaObjectStateChangeObserverCallback::DoCancel() sl@0: { sl@0: //nothing to cancel sl@0: } sl@0: sl@0: sl@0: //**************************************** sl@0: // CMMFFindAndOpenController sl@0: //**************************************** sl@0: sl@0: /** sl@0: * Factory function to create a CMMFFindAndOpenController class sl@0: * sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C CMMFFindAndOpenController* CMMFFindAndOpenController::NewL(MMMFFindAndOpenControllerObserver& aObserver) sl@0: { sl@0: CMMFFindAndOpenController* self = new(ELeave) CMMFFindAndOpenController(aObserver); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: CMMFFindAndOpenController::~CMMFFindAndOpenController() sl@0: { sl@0: Cancel(); sl@0: sl@0: // delete temporary variables sl@0: Close(); sl@0: sl@0: // this should cancel the AO sl@0: delete iAddDataSourceSinkAsync; sl@0: sl@0: delete iPrimaryConfig; sl@0: delete iSecondaryConfig; sl@0: } sl@0: sl@0: /** sl@0: * Function to free up memory after a successful open has completed sl@0: * Useful to allow a alloc testing to work. sl@0: * Must not be called if ReOpen() is to be called sl@0: * sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C void CMMFFindAndOpenController::Close() sl@0: { sl@0: sl@0: Cancel(); sl@0: sl@0: if(iAddDataSourceSinkAsync) sl@0: { sl@0: iAddDataSourceSinkAsync->Cancel(); sl@0: } sl@0: sl@0: if (iPrimaryConfig) sl@0: iPrimaryConfig->Close(); sl@0: if (iSecondaryConfig) sl@0: iSecondaryConfig->Close(); sl@0: sl@0: iPrioritisedControllers.Close(); sl@0: iControllers.ResetAndDestroy(); sl@0: iControllers.Close(); sl@0: sl@0: iFileName.SetLength(0); sl@0: iFileNameSecondary.SetLength(0); sl@0: sl@0: delete iUrl; sl@0: iUrl = NULL; sl@0: sl@0: delete iMimeType; sl@0: iMimeType = NULL; sl@0: sl@0: delete iUniqueId; sl@0: iUniqueId = NULL; sl@0: sl@0: if (iOwnFileHandle) sl@0: { sl@0: iFileHandle.Close(); sl@0: iOwnFileHandle = EFalse; sl@0: } sl@0: } sl@0: /** sl@0: * Function to free up memory of which is not required in ReOpen() sl@0: * after a successful open has completed sl@0: * Useful to allow a alloc testing to work. sl@0: * sl@0: * @internalComponent sl@0: */ sl@0: sl@0: EXPORT_C void CMMFFindAndOpenController::CloseConfig() sl@0: { sl@0: Cancel(); sl@0: if(iAddDataSourceSinkAsync) sl@0: { sl@0: iAddDataSourceSinkAsync->Cancel(); sl@0: } sl@0: sl@0: if (iSecondaryConfig) sl@0: { sl@0: iSecondaryConfig->Close(); sl@0: } sl@0: sl@0: iPrioritisedControllers.Close(); sl@0: iControllers.ResetAndDestroy(); sl@0: iControllers.Close(); sl@0: sl@0: iFileName.SetLength(0); sl@0: iFileNameSecondary.SetLength(0); sl@0: sl@0: delete iUrl; sl@0: iUrl = NULL; sl@0: sl@0: delete iMimeType; sl@0: iMimeType = NULL; sl@0: sl@0: delete iUniqueId; sl@0: iUniqueId = NULL; sl@0: sl@0: if (iOwnFileHandle) sl@0: { sl@0: iFileHandle.Close(); sl@0: iOwnFileHandle = EFalse; sl@0: } sl@0: } sl@0: sl@0: CMMFFindAndOpenController::CMMFFindAndOpenController(MMMFFindAndOpenControllerObserver& aObserver) : sl@0: CActive(EPriorityStandard), sl@0: iObserver(aObserver), sl@0: iDescriptor(NULL, 0) sl@0: { sl@0: CActiveScheduler::Add(this); sl@0: } sl@0: sl@0: void CMMFFindAndOpenController::ConstructL() sl@0: { sl@0: iAddDataSourceSinkAsync = CMMFAddDataSourceSinkAsync::NewL(*this); sl@0: iPrimaryConfig = new (ELeave) CConfig(); sl@0: iSecondaryConfig = new (ELeave) CConfig; sl@0: iCurrentConfig = iPrimaryConfig; sl@0: sl@0: RProcess thisProcess; sl@0: iHasDrmCapability = thisProcess.HasCapability(ECapabilityDRM, KSuppressPlatSecDiagnostic); sl@0: thisProcess.Close(); sl@0: } sl@0: sl@0: void CMMFFindAndOpenController::RunL() sl@0: { sl@0: Process(); sl@0: } sl@0: sl@0: void CMMFFindAndOpenController::DoCancel() sl@0: { sl@0: iAddDataSourceSinkAsync->Cancel(); sl@0: } sl@0: sl@0: /** sl@0: * Defines the media ID & priority to be used when opening a controller sl@0: * Normally called once only after class has been constructed sl@0: * sl@0: * @param aMediaId sl@0: * the media ID to use when searching for a controller sl@0: * e.g. KUidMediaTypeAudio sl@0: * @param aPrioritySettings sl@0: * the priority settings to use when opening a controller sl@0: * @param aMediaIdMatchType sl@0: * Defines the type of media id match to be performed on the plugins sl@0: * returned from the ECOM registry. sl@0: * @leave can leave with KErrNoMemory sl@0: sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C void CMMFFindAndOpenController::Configure( sl@0: TUid aMediaId, sl@0: TMMFPrioritySettings aPrioritySettings, sl@0: CMMFPluginSelectionParameters::TMediaIdMatchType aMediaIdMatchType) sl@0: { sl@0: iPrioritySettings = aPrioritySettings; sl@0: sl@0: iMediaIdMatchType = aMediaIdMatchType; sl@0: sl@0: iMediaId = aMediaId; sl@0: } sl@0: sl@0: void CMMFFindAndOpenController::ConfigureController( sl@0: CConfig& config, sl@0: RMMFController& aController, sl@0: CMMFControllerEventMonitor& aEventMonitor, sl@0: TControllerMode aControllerMode) sl@0: { sl@0: config.iController = &aController; sl@0: config.iEventMonitor = &aEventMonitor; sl@0: config.iControllerMode = aControllerMode; sl@0: } sl@0: sl@0: /** sl@0: * Configures the primary controller sl@0: * sl@0: * @param aController sl@0: * a reference to the client controller object to use sl@0: * @param aEventMonitor sl@0: * a reference to an event monitor object for receiving sl@0: * events from the controller sl@0: * @param aControllerMode sl@0: * indicates whether this controller is to be used for recording sl@0: * or playback sl@0: * sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C void CMMFFindAndOpenController::ConfigureController( sl@0: RMMFController& aController, sl@0: CMMFControllerEventMonitor& aEventMonitor, sl@0: TControllerMode aControllerMode) sl@0: { sl@0: ConfigureController( sl@0: *iPrimaryConfig, sl@0: aController, sl@0: aEventMonitor, sl@0: aControllerMode); sl@0: } sl@0: sl@0: /** sl@0: * Configures the secondary controller sl@0: * sl@0: * This is only needed for the audio recorder utility which opens sl@0: * one controller for playback and another for recording sl@0: * sl@0: * @param aController sl@0: * a reference to the client controller object to use sl@0: * @param aEventMonitor sl@0: * a reference to an event monitor object for receiving sl@0: * events from the controller sl@0: * @param aControllerMode sl@0: * indicates whether this controller is to be used for recording sl@0: * or playback or converting sl@0: * sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C void CMMFFindAndOpenController::ConfigureSecondaryController( sl@0: RMMFController& aController, sl@0: CMMFControllerEventMonitor& aEventMonitor, sl@0: TControllerMode aControllerMode) sl@0: { sl@0: ConfigureController( sl@0: *iSecondaryConfig, sl@0: aController, sl@0: aEventMonitor, sl@0: aControllerMode); sl@0: } sl@0: sl@0: /** sl@0: * Makes any controllers that are opened subsequently share a single heap. sl@0: * sl@0: * The default behaviour is that each controller is created with its own heap. sl@0: * Each heap uses a chunk, so using this function avoids situations where the number sl@0: * of chunks per process is limited. sl@0: * The default behaviour is generally to be preferred, and should give lower overall sl@0: * memory usage. However, if many controllers are to be created for a particular thread, sl@0: * then this function should be used to prevent running out of heaps or chunks. sl@0: * sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C void CMMFFindAndOpenController::UseSharedHeap() sl@0: { sl@0: iUseSharedHeap = ETrue; sl@0: } sl@0: sl@0: void CMMFFindAndOpenController::Init() sl@0: { sl@0: // This should be called prior to opening, so reset the error sl@0: iError = KErrNone; sl@0: iSourceSinkConfigured = EFalse; sl@0: iControllerCount = 0; sl@0: } sl@0: sl@0: void CMMFFindAndOpenController::ConfigureSourceSink( sl@0: CConfig& config, sl@0: TSourceSink aSource, sl@0: TSourceSink aSink) sl@0: { sl@0: TInt err; sl@0: TRAP(err, config.iSource = CreateSourceSinkL(aSource)); sl@0: if (err != KErrNone) sl@0: { sl@0: iError = err; sl@0: return; sl@0: } sl@0: sl@0: TRAP(err, config.iSink = CreateSourceSinkL(aSink)); sl@0: if (err != KErrNone) sl@0: { sl@0: iError = err; sl@0: return; sl@0: } sl@0: } sl@0: sl@0: sl@0: void CMMFFindAndOpenController::ConfigureSourceSink( sl@0: CConfig& config, sl@0: const TMMSource& aSource, sl@0: TSourceSink aSink) sl@0: { sl@0: TInt err; sl@0: TRAP(err, config.iSource = CreateSourceSinkL(aSource)); sl@0: if (err != KErrNone) sl@0: { sl@0: iError = err; sl@0: return; sl@0: } sl@0: sl@0: TRAP(err, config.iSink = CreateSourceSinkL(aSink)); sl@0: if (err != KErrNone) sl@0: { sl@0: iError = err; sl@0: return; sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: /** sl@0: * Configure the primary controller's source and sink sl@0: * The descriptors passed to this function are copied so they do not need to be persistent. sl@0: * To simplify the API, any errors that occur are reported back asynchronously following sl@0: * a subsequent call to OpenByXXX() sl@0: * sl@0: * @param aSourceUid sl@0: * the UID of the data source sl@0: * @param aSourceData sl@0: * a reference to a descriptor used to configure the source sl@0: * @param aSinkUid sl@0: * the UID of the data sink sl@0: * @param aSinkData sl@0: * a reference to a descriptor used to configure the sink sl@0: * sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C void CMMFFindAndOpenController::ConfigureSourceSink( sl@0: TSourceSink aSource, sl@0: TSourceSink aSink) sl@0: { sl@0: sl@0: CConfig* config = NULL; sl@0: sl@0: Init(); sl@0: config = iPrimaryConfig; sl@0: sl@0: sl@0: // must have already called ConfigureController() sl@0: __ASSERT_ALWAYS(config->iController != NULL, CUPanic(EMMFMediaClientUtilityBadState)); sl@0: sl@0: ConfigureSourceSink( sl@0: *config, sl@0: aSource, sl@0: aSink); sl@0: iCurrentConfig = config; sl@0: sl@0: iSourceSinkConfigured = ETrue; sl@0: } sl@0: sl@0: sl@0: /** sl@0: * Configure the primary controller's source and sink sl@0: * The descriptors passed to this function are copied so they do not need to be persistent. sl@0: * To simplify the API, any errors that occur are reported back asynchronously following sl@0: * a subsequent call to OpenByXXX() sl@0: * sl@0: * @param aSourceUid sl@0: * the UID of the data source sl@0: * @param aSourceData sl@0: * a reference to a descriptor used to configure the source sl@0: * @param aSinkUid sl@0: * the UID of the data sink sl@0: * @param aSinkData sl@0: * a reference to a descriptor used to configure the sink sl@0: * sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C void CMMFFindAndOpenController::ConfigureSecondarySourceSink( sl@0: TSourceSink aSource, sl@0: TSourceSink aSink) sl@0: { sl@0: if (iError != KErrNone) sl@0: { sl@0: // if there was an error configuring the primary source/sink, do not try the secondary one sl@0: // Don't return the error, since the stored error will be returned by the OpenBy... method sl@0: return; sl@0: } sl@0: sl@0: CConfig* config = NULL; sl@0: sl@0: config = iSecondaryConfig; sl@0: sl@0: // must have already configured the primary controller sl@0: __ASSERT_ALWAYS(iSourceSinkConfigured, CUPanic(EMMFMediaClientUtilityBadState)); sl@0: config = iSecondaryConfig; sl@0: sl@0: // must have already called ConfigureController() sl@0: __ASSERT_ALWAYS(config->iController != NULL, CUPanic(EMMFMediaClientUtilityBadState)); sl@0: sl@0: ConfigureSourceSink( sl@0: *config, sl@0: aSource, sl@0: aSink); sl@0: iCurrentConfig = config; sl@0: sl@0: iSourceSinkConfigured = ETrue; sl@0: } sl@0: sl@0: sl@0: sl@0: EXPORT_C void CMMFFindAndOpenController::ConfigureSourceSink( sl@0: const TMMSource& aSource, sl@0: TSourceSink aSink) sl@0: { sl@0: Init(); sl@0: CConfig* config = iPrimaryConfig; sl@0: sl@0: // must have already called ConfigureController() sl@0: __ASSERT_ALWAYS(config->iController != NULL, CUPanic(EMMFMediaClientUtilityBadState)); sl@0: sl@0: ConfigureSourceSink( sl@0: *config, sl@0: aSource, sl@0: aSink); sl@0: iCurrentConfig = config; sl@0: sl@0: iSourceSinkConfigured = ETrue; sl@0: } sl@0: sl@0: sl@0: sl@0: /** sl@0: * Opens a controller using the supplied controller UID sl@0: * and adds the source & sink sl@0: * Completion is indicated asynchonously by a call to MfaocComplete() sl@0: * sl@0: * @param aControllerUid sl@0: * the UID of the primary controller sl@0: * @param aControllerUid sl@0: * the UID of the secondary controller sl@0: * sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C void CMMFFindAndOpenController::OpenByControllerUid( sl@0: TUid aControllerUid, sl@0: TUid aSecondaryControllerUid) sl@0: { sl@0: // must have already called ConfigureSourceSink() sl@0: __ASSERT_ALWAYS(iSourceSinkConfigured, CUPanic(EMMFMediaClientUtilityBadState)); sl@0: sl@0: // Have there been any errors so far ? sl@0: if (iError != KErrNone) sl@0: { sl@0: SchedSendError(); sl@0: return; sl@0: } sl@0: sl@0: if (iCurrentConfig == iPrimaryConfig) sl@0: { sl@0: // only do this for the playback controller sl@0: TRAP(iError, iCurrentConfig->iSource->EvaluateIntentL()) sl@0: sl@0: if (iError != KErrNone && sl@0: !(iCurrentConfig->iControllerMode == EPlayback && iError == KErrPermissionDenied && !iHasDrmCapability)) sl@0: { sl@0: // KErrPermissionDenied error and no DRM capability are not problems in Playback mode sl@0: // proper action will be performed when controller is loaded sl@0: SchedSendError(); sl@0: return; sl@0: } sl@0: } sl@0: sl@0: iPrimaryConfig->iControllerUid = aControllerUid; sl@0: if (iCurrentConfig == iSecondaryConfig) sl@0: { sl@0: if (aSecondaryControllerUid == KNullUid) sl@0: iSecondaryConfig->iControllerUid = aControllerUid; sl@0: else sl@0: iSecondaryConfig->iControllerUid = aSecondaryControllerUid; sl@0: } sl@0: sl@0: iMode = EOpenByControllerUid; sl@0: iControllerImplInfo = NULL; sl@0: iState = EOpenController; sl@0: KickState(); sl@0: } sl@0: sl@0: /** sl@0: * Opens a controller using the supplied file name sl@0: * and adds the source & sink sl@0: * A copy is made of the filename or file handle so that it need not be persistent sl@0: * Completion is indicated asynchonously by a call to MfaocComplete() sl@0: * sl@0: * @param aSource sl@0: * a reference to a TFileSource object to be used when searching sl@0: * for a controller sl@0: * @param aFileNameSecondary sl@0: * a reference to the seconday filename to be used when searching sl@0: * for a controller. This need only be supplied when converting sl@0: * between two files. sl@0: * sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C void CMMFFindAndOpenController::OpenByFileSource(const TMMSource& aSource, const TDesC& aFileNameSecondary) sl@0: { sl@0: // must have already called ConfigureSourceSink() sl@0: __ASSERT_ALWAYS(iSourceSinkConfigured, CUPanic(EMMFMediaClientUtilityBadState)); sl@0: sl@0: TInt err; sl@0: // Have there been any errors so far ? sl@0: if (iError != KErrNone) sl@0: { sl@0: SchedSendError(); sl@0: return; sl@0: } sl@0: sl@0: if (iOwnFileHandle) sl@0: { sl@0: // in case of error sl@0: iFileHandle.Close(); sl@0: iOwnFileHandle = EFalse; sl@0: } sl@0: sl@0: iEnableUi = aSource.IsUIEnabled(); sl@0: if (aSource.SourceType()==KUidMMFileSource) sl@0: { sl@0: const TMMFileSource& fileSource = static_cast(aSource); sl@0: iFileName = fileSource.Name(); sl@0: iUseFileHandle = EFalse; sl@0: } sl@0: sl@0: if (aSource.SourceType()==KUidMMFileHandleSource) sl@0: { sl@0: const TMMFileHandleSource& fileHandleSource = static_cast(aSource); sl@0: ASSERT(iFileHandle.SubSessionHandle()==0); // closed just above sl@0: err = iFileHandle.Duplicate(fileHandleSource.Handle()); sl@0: if (err != KErrNone) sl@0: { sl@0: SchedSendError(err); sl@0: return; sl@0: } sl@0: iFileHandle.Name(iFileName); //ignore error return since we'll just do without the filename if not available sl@0: iUseFileHandle = ETrue; sl@0: iOwnFileHandle = ETrue; // because we dup'd it sl@0: } sl@0: sl@0: TRAP(err, iUniqueId = aSource.UniqueId().AllocL()); sl@0: iIntent = aSource.Intent(); sl@0: if (err != KErrNone) sl@0: { sl@0: SchedSendError(err); sl@0: return; sl@0: } sl@0: sl@0: sl@0: // take a copy of the secondary file name sl@0: iFileNameSecondary = aFileNameSecondary; sl@0: sl@0: iMode = EOpenByFileName; sl@0: iState = EBuildControllerList; sl@0: KickState(); sl@0: } sl@0: sl@0: /** sl@0: * Opens a controller using the supplied format UID sl@0: * and adds the source & sink sl@0: * Completion is indicated asynchonously by a call to MfaocComplete() sl@0: * sl@0: * @param aFormatUid sl@0: * the UID of a format that must be supported by the controller sl@0: * @param aFormatUidSecondary sl@0: * the UID of a secondary format that must be supported by the controller sl@0: * This need only be supplied when converting between two differnet formats. sl@0: * sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C void CMMFFindAndOpenController::OpenByFormatUid(TUid aFormatUid, TUid aFormatUidSecondary) sl@0: { sl@0: // must have already called ConfigureSourceSink() sl@0: __ASSERT_ALWAYS(iSourceSinkConfigured, CUPanic(EMMFMediaClientUtilityBadState)); sl@0: sl@0: // Have there been any errors so far ? sl@0: if (iError != KErrNone) sl@0: { sl@0: SchedSendError(); sl@0: return; sl@0: } sl@0: sl@0: iFormatUid = aFormatUid; sl@0: iFormatUidSecondary = aFormatUidSecondary; sl@0: sl@0: iMode = EOpenByFormatUid; sl@0: iState = EBuildControllerList; sl@0: KickState(); sl@0: } sl@0: sl@0: /** sl@0: * Opens a controller using the supplied descriptor sl@0: * and adds the source & sink sl@0: * Completion is indicated asynchonously by a call to MfaocComplete() sl@0: * sl@0: * @param aDescriptor sl@0: * a reference to the descriptor to be used when searching sl@0: * for a controller sl@0: * sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C void CMMFFindAndOpenController::OpenByDescriptor(const TDesC8& aDescriptor) sl@0: { sl@0: // must have already called ConfigureSourceSink() sl@0: __ASSERT_ALWAYS(iSourceSinkConfigured, CUPanic(EMMFMediaClientUtilityBadState)); sl@0: sl@0: // Have there been any errors so far ? sl@0: if (iError != KErrNone) sl@0: { sl@0: SchedSendError(); sl@0: return; sl@0: } sl@0: sl@0: // take a copy of the descriptor sl@0: TUint8* desBufferPtr = const_cast (aDescriptor.Ptr()); sl@0: iDescriptor.Set( desBufferPtr,aDescriptor.Length(),aDescriptor.Length()); sl@0: sl@0: iMode = EOpenByDescriptor; sl@0: iState = EBuildControllerList; sl@0: KickState(); sl@0: } sl@0: sl@0: /** sl@0: * Opens a controller using the supplied URL sl@0: * and adds the source & sink sl@0: * Completion is indicated asynchonously by a call to MfaocComplete() sl@0: * sl@0: * @param aUrl sl@0: * a reference to the URL to be used when searching for a controller sl@0: * @param aIapId sl@0: * the IAP ID to be used when searching for a controller sl@0: * @param aMimeType sl@0: * the MIME type of the data to be used when searching for a controller sl@0: * sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C void CMMFFindAndOpenController::OpenByUrl(const TDesC& aUrl, TInt aIapId, const TDesC8& aMimeType) sl@0: { sl@0: // must have already called ConfigureSourceSink() sl@0: __ASSERT_ALWAYS(iSourceSinkConfigured, CUPanic(EMMFMediaClientUtilityBadState)); sl@0: sl@0: // Have there been any errors so far ? sl@0: if (iError != KErrNone) sl@0: { sl@0: SchedSendError(); sl@0: return; sl@0: } sl@0: sl@0: // take a copy of the Url sl@0: delete iUrl; sl@0: iUrl = NULL; sl@0: iUrl = aUrl.Alloc(); sl@0: if (iUrl == NULL) sl@0: { sl@0: SchedSendError(KErrNoMemory); sl@0: return; sl@0: } sl@0: sl@0: // take a copy of the IapId sl@0: iIapId = aIapId; sl@0: sl@0: // take a copy of the mime type sl@0: delete iMimeType; sl@0: iMimeType = NULL; sl@0: iMimeType = aMimeType.Alloc(); sl@0: if (iMimeType == NULL) sl@0: { sl@0: SchedSendError(KErrNoMemory); sl@0: return; sl@0: } sl@0: sl@0: iMode = EOpenByUrl; sl@0: iState = EBuildControllerList; sl@0: KickState(); sl@0: } sl@0: sl@0: /** sl@0: * Static function to return a TMMFFileConfig object sl@0: * suitable for passing to ConfigureSourceSink() sl@0: * sl@0: * @param aFileName sl@0: * the filename to use sl@0: * sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C TMMFFileConfig CMMFFindAndOpenController::GetConfigFile(const TDesC& aFileName) sl@0: { sl@0: TMMFFileConfig sourceSinkData; sl@0: sourceSinkData().iPath = aFileName; sl@0: return sourceSinkData; sl@0: } sl@0: sl@0: /** sl@0: * Static function to return a TMMFDescriptorConfig object sl@0: * suitable for passing to ConfigureSourceSink() sl@0: * sl@0: * @param aFileName sl@0: * the filename to use sl@0: * sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C TMMFDescriptorConfig CMMFFindAndOpenController::GetConfigDescriptor(const TDesC8& aDescriptor) sl@0: { sl@0: TMMFDescriptorConfig sourceSinkData; sl@0: sourceSinkData().iDes = (TAny*)&aDescriptor; sl@0: sourceSinkData().iDesThreadId = RThread().Id(); sl@0: return sourceSinkData; sl@0: } sl@0: sl@0: /** sl@0: * Static function to create a CBufFlat object sl@0: * suitable for passing to ConfigureSourceSink() sl@0: * sl@0: * @param aUrlCfgBuffer sl@0: * the reference to a caller-supplied pointer used to create sl@0: * a CBufFlat object. The caller is responsible for deletion. sl@0: * @param aUrl sl@0: * a reference to the URL to be used sl@0: * @param aIapId sl@0: * the IAP ID to be used sl@0: * @return can return KErrNone or KErrNoMemory sl@0: * sl@0: * @internalComponent sl@0: */ sl@0: sl@0: EXPORT_C void CMMFFindAndOpenController::GetConfigUrlL(CBufFlat*& aUrlCfgBuffer, const TDesC& aUrl, TInt aIapId) sl@0: { sl@0: delete aUrlCfgBuffer; sl@0: aUrlCfgBuffer = NULL; sl@0: sl@0: CMMFUrlParams* urlCfg = CMMFUrlParams::NewL(aUrl,aIapId); sl@0: CleanupStack::PushL(urlCfg); sl@0: aUrlCfgBuffer = urlCfg->ExternalizeToCBufFlatLC(); sl@0: CleanupStack::Pop(aUrlCfgBuffer); sl@0: CleanupStack::PopAndDestroy(urlCfg); sl@0: } sl@0: /** sl@0: * ReOpens the previously opened primary controller sl@0: * sl@0: * @internalComponent sl@0: */ sl@0: EXPORT_C void CMMFFindAndOpenController::ReOpen() sl@0: { sl@0: // should already have a valid controller uid so just open it sl@0: iControllerImplInfo = NULL; sl@0: iState = EOpenController; sl@0: KickState(); sl@0: } sl@0: sl@0: void CMMFFindAndOpenController::OpenPrimaryController(void) sl@0: { sl@0: iCurrentConfig = iPrimaryConfig; sl@0: switch(iMode) sl@0: { sl@0: case EOpenByFileName: sl@0: case EOpenByFormatUid: sl@0: case EOpenByDescriptor: sl@0: case EOpenByUrl: sl@0: iState = EBuildControllerList; sl@0: break; sl@0: case EOpenByControllerUid: sl@0: iControllerImplInfo = NULL; sl@0: iState = EOpenController; sl@0: break; sl@0: } sl@0: KickState(); sl@0: } sl@0: sl@0: void CMMFFindAndOpenController::KickState() sl@0: { sl@0: TRequestStatus* status = &iStatus; sl@0: User::RequestComplete(status, KErrNone); sl@0: SetActive(); sl@0: } sl@0: sl@0: void CMMFFindAndOpenController::CloseController() sl@0: { sl@0: if (iCurrentConfig->iEventMonitor) sl@0: iCurrentConfig->iEventMonitor->Cancel(); sl@0: iCurrentConfig->iController->Close(); sl@0: } sl@0: sl@0: void CMMFFindAndOpenController::Process() sl@0: { sl@0: switch(iState) sl@0: { sl@0: case EBuildControllerList: sl@0: switch(iMode) sl@0: { sl@0: case EOpenByFileName: sl@0: TRAP(iError, BuildControllerListFileNameL()); sl@0: break; sl@0: case EOpenByDescriptor: sl@0: TRAP(iError, BuildControllerListDescriptorL()); sl@0: break; sl@0: case EOpenByUrl: sl@0: TRAP(iError, BuildControllerListUrlL()); sl@0: break; sl@0: case EOpenByFormatUid: sl@0: TRAP(iError, BuildControllerListFormatL()); sl@0: break; sl@0: default: sl@0: CUPanic(EMMFMediaClientUtilityBadState); sl@0: } sl@0: sl@0: if (iError != KErrNone) sl@0: { sl@0: iState = EIdle; sl@0: SendError(); sl@0: break; sl@0: } sl@0: sl@0: // try the first controller sl@0: iControllerIndex = -1; sl@0: TryNextController(); sl@0: break; sl@0: sl@0: case EOpenController: sl@0: { sl@0: // Make sure any existing controller is closed. sl@0: CloseController(); sl@0: sl@0: TBool isSecureDrmProcess = EFalse;// need to keep it false as UseSecureDRMProcess may return error sl@0: // Loading controller in new threading model is enabled only in playback mode sl@0: TUid sourceUid = iCurrentConfig->iSource->SourceSinkUid(); sl@0: TBool localPlaybackMode = iCurrentConfig->iControllerMode == EPlayback && sl@0: (sourceUid == KUidMmfFileSource || sourceUid == KUidMmfDescriptorSource); sl@0: if(localPlaybackMode) sl@0: { sl@0: TRAPD(err,UseSecureDRMProcessL(isSecureDrmProcess)); sl@0: if(err == KErrPermissionDenied) sl@0: { sl@0: isSecureDrmProcess = ETrue; sl@0: } sl@0: else if(err != KErrNone) sl@0: { sl@0: iError = err; sl@0: SendError(err); sl@0: return; sl@0: } sl@0: } sl@0: // Open the controller sl@0: if (iControllerImplInfo) sl@0: { sl@0: if(isSecureDrmProcess && localPlaybackMode) sl@0: { sl@0: iError = iCurrentConfig->iController->OpenInSecureDRMProcess(*iControllerImplInfo, iPrioritySettings, iUseSharedHeap); sl@0: iUsingSecureDrmProcess = ETrue; sl@0: } sl@0: else sl@0: { sl@0: iError = iCurrentConfig->iController->Open(*iControllerImplInfo, iPrioritySettings, iUseSharedHeap); sl@0: iUsingSecureDrmProcess = EFalse;; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: if(isSecureDrmProcess && localPlaybackMode) sl@0: { sl@0: iError = iCurrentConfig->iController->OpenInSecureDRMProcess(iCurrentConfig->iControllerUid, iPrioritySettings, iUseSharedHeap); sl@0: iUsingSecureDrmProcess = ETrue; sl@0: sl@0: } sl@0: else sl@0: { sl@0: iError = iCurrentConfig->iController->Open(iCurrentConfig->iControllerUid, iPrioritySettings, iUseSharedHeap); sl@0: iUsingSecureDrmProcess = EFalse; sl@0: } sl@0: } sl@0: //in case of error, including KErrNomemory try next controller sl@0: if (iError) sl@0: { sl@0: TryNextController(); sl@0: } sl@0: else sl@0: { sl@0: #ifdef SYMBIAN_ENABLE_MMF_MULTISCREEN_SUPPORT sl@0: #ifndef SYMBIAN_BUILD_GCE sl@0: if(iCurrentConfig->iControllerMode == EPlayback && iMediaId == KUidMediaTypeVideo) sl@0: { sl@0: iError = iVideoSetInitScreenCustomCommands->SetInitScreenNumber(iScreenNumber); sl@0: if(iError) sl@0: { sl@0: if (iError == KErrNotSupported && iScreenNumber == KDefaultScreenNo) sl@0: { sl@0: iError = KErrNone; sl@0: } sl@0: else sl@0: { sl@0: iState = EIdle; sl@0: SendError(); sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: #endif // SYMBIAN_BUILD_GCE sl@0: #endif // SYMBIAN_ENABLE_MMF_MULTISCREEN_SUPPORT sl@0: iCurrentConfig->iEventMonitor->Start(); sl@0: sl@0: if (iCurrentConfig == iSecondaryConfig) sl@0: { sl@0: iState = EAddSource; sl@0: KickState(); sl@0: } sl@0: else sl@0: { sl@0: iState = EAddSink; sl@0: KickState(); sl@0: } sl@0: } sl@0: } sl@0: break; sl@0: sl@0: case EAddSource: sl@0: { sl@0: iState = EWaitingForSource; sl@0: const CMMSourceSink* source = iCurrentConfig->iSource; sl@0: // CMMSourceSink has the ability to transform the data it stored into a data stream sl@0: // which can be passed to CMMFAddDataSourceSinkAsync for further processing. sl@0: // CMMFileSourceSink, which is a specialized CMMSourceSink, stores info about a file sl@0: // source/sink. The info about the file can be a file path or a file handle. sl@0: // When it holds a file handle and turns info into data stream, the file handle is sl@0: // stored as a pointer in the stream. However, at this point, it cannot guarantee that sl@0: // the streamed info is always extracted within the same process. If the pointer is sl@0: // dereferenced in other process, a panic will raise in the system. Therefore, a file sl@0: // handle, rather than pointer, is used when necessary. sl@0: if (iUsingSecureDrmProcess && source->CarryingFileHandle()) sl@0: { sl@0: iAddDataSourceSinkAsync->AddFileHandleDataSource(*iCurrentConfig->iController, sl@0: static_cast(source)->FileHandle(), sl@0: source->SourceSinkData()); sl@0: } sl@0: else sl@0: { sl@0: iAddDataSourceSinkAsync->AddDataSource(*iCurrentConfig->iController, sl@0: source->SourceSinkUid(), sl@0: source->SourceSinkData()); sl@0: } sl@0: } sl@0: break; sl@0: sl@0: case EAddSink: sl@0: { sl@0: iState = EWaitingForSink; sl@0: const CMMSourceSink* sink = iCurrentConfig->iSink; sl@0: // CMMSourceSink has the ability to transform the data it stored into a data stream sl@0: // which can be passed to CMMFAddDataSourceSinkAsync for further processing. sl@0: // CMMFileSourceSink, which is a specialized CMMSourceSink, stores info about a file sl@0: // source/sink. The info about the file can be a file path or a file handle. sl@0: // When it holds a file handle and turns info into data stream, the file handle is sl@0: // stored as a pointer in the stream. However, at this point, it cannot guarantee that sl@0: // the streamed info is always extracted within the same process. If the pointer is sl@0: // dereferenced in other process, a panic will raise in the system. Therefore, a file sl@0: // handle, rather than pointer, is used when necessary. sl@0: const TDesC8& sinkData = sink->SourceSinkData(); sl@0: if (iUsingSecureDrmProcess && sink->CarryingFileHandle()) sl@0: { sl@0: iAddDataSourceSinkAsync->AddFileHandleDataSink(*iCurrentConfig->iController, sl@0: static_cast(sink)->FileHandle(), sl@0: sinkData); sl@0: } sl@0: else sl@0: { sl@0: iAddDataSourceSinkAsync->AddDataSink(*iCurrentConfig->iController, sl@0: sink->SourceSinkUid(), sl@0: sinkData); sl@0: } sl@0: } sl@0: break; sl@0: sl@0: case EWaitingForSource: sl@0: break; sl@0: sl@0: case EWaitingForSink: sl@0: break; sl@0: sl@0: case ESendError: sl@0: SendError(); sl@0: iState = EIdle; sl@0: break; sl@0: sl@0: case EIdle: sl@0: default: sl@0: break; sl@0: } sl@0: } sl@0: sl@0: void CMMFFindAndOpenController::TryNextController() sl@0: { sl@0: // If an error occurred close the controller. sl@0: if (iError != KErrNone) sl@0: { sl@0: CloseController(); sl@0: } sl@0: sl@0: iStopTryLoadController = EFalse; sl@0: sl@0: if (iMode == EOpenByControllerUid || ++iControllerIndex >= iControllerCount) sl@0: { sl@0: //Raise a flag to stop trying to load the controllers sl@0: iStopTryLoadController = ETrue; sl@0: sl@0: // KErrNotSupported is the default error, but will only be used if no other error sl@0: // has been discovered (the first error found is used by default) sl@0: // However, KErrBadHandle seems to mean that we tried to use the DRM server without sl@0: // RFs::ShareProtected() having been called, so force usage of KErrNotSupported so sl@0: // client does not see changed sl@0: TBool forceErrorUse = EFalse; sl@0: if (iError==KErrBadHandle) sl@0: { sl@0: forceErrorUse = ETrue; sl@0: } sl@0: SendError(KErrNotSupported, forceErrorUse); sl@0: sl@0: return; sl@0: } sl@0: sl@0: if (iMode == EOpenByFileName || iMode == EOpenByFormatUid) sl@0: { sl@0: iControllerImplInfo = iPrioritisedControllers[iControllerIndex]; sl@0: } sl@0: else //if (iMode == EOpenByDescriptor || iMode == EOpenByUrl) sl@0: { sl@0: iControllerImplInfo = iControllers[iControllerIndex]; sl@0: } sl@0: sl@0: iCurrentConfig->iControllerUid = iControllerImplInfo->Uid(); sl@0: iState = EOpenController; sl@0: KickState(); sl@0: } sl@0: sl@0: void CMMFFindAndOpenController::MadssaoAddDataSourceSinkAsyncComplete(TInt aError, const TMMFMessageDestination& aHandle) sl@0: { sl@0: iError = aError; sl@0: sl@0: // take the first available exit if we're out of memory sl@0: // or we've been cancelled sl@0: if (iError == KErrNoMemory || iError == KErrCancel) sl@0: { sl@0: SendError(); sl@0: return; sl@0: } sl@0: sl@0: // failed to add source or sink - try the next controller sl@0: if (aError != KErrNone) sl@0: { sl@0: TryNextController(); sl@0: return; sl@0: } sl@0: sl@0: if (iState == EWaitingForSource) sl@0: { sl@0: #ifdef SYMBIAN_ENABLE_MMF_MULTISCREEN_SUPPORT sl@0: #ifdef SYMBIAN_BUILD_GCE sl@0: // If surfaces are required try to use them. If this fails then fall back to using sl@0: // direct screen access. sl@0: if(iCurrentConfig->iControllerMode == EPlayback && iMediaId == KUidMediaTypeVideo) sl@0: { sl@0: // UseSurfaces call has to be done after adding data sink and adding data source. sl@0: iSurfaceSupported = iVideoPlaySurfaceSupportCustomCommands->UseSurfaces(); sl@0: sl@0: if (iSurfaceSupported == KErrNotSupported) sl@0: { sl@0: if (iUseVPU2) sl@0: { sl@0: if (ControllerIndex() < ControllerCount() - 1) sl@0: { sl@0: // Until end of the list of controllers, sl@0: // try the next one for surface support sl@0: TryNextController(); // this will also kick-state sl@0: return; sl@0: } sl@0: else sl@0: { sl@0: iError = iSurfaceSupported; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // No surface enabled controller found sl@0: // not required to do only surface, sl@0: // use the last one that matched. sl@0: iError = iVideoSetInitScreenCustomCommands->SetInitScreenNumber(iScreenNumber); sl@0: if (iError == KErrNotSupported && iScreenNumber == KDefaultScreenNo) sl@0: { sl@0: iError = KErrNone; sl@0: } sl@0: } sl@0: } sl@0: else sl@0: { sl@0: iError = iSurfaceSupported; sl@0: } sl@0: } sl@0: #endif // SYMBIAN_BUILD_GCE sl@0: #endif // SYMBIAN_ENABLE_MMF_MULTISCREEN_SUPPORT sl@0: sl@0: iSourceHandle = aHandle; sl@0: if (iCurrentConfig == iSecondaryConfig) sl@0: { sl@0: iState = EAddSink; sl@0: } sl@0: else // completed ok ! sl@0: { sl@0: iState = EIdle; sl@0: SendError(KErrNone, ETrue); sl@0: return; sl@0: } sl@0: } sl@0: else if (iState == EWaitingForSink) sl@0: { sl@0: iSinkHandle = aHandle; sl@0: if (iCurrentConfig == iSecondaryConfig) // completed ok ! sl@0: { sl@0: iState = EIdle; sl@0: iError = KErrNone; sl@0: SendError(); sl@0: return; sl@0: } sl@0: else sl@0: { sl@0: iState = EAddSource; sl@0: } sl@0: } sl@0: sl@0: KickState(); sl@0: } sl@0: sl@0: void CMMFFindAndOpenController::SendError(TInt aError, TBool aOverrideError) sl@0: { sl@0: if (iError == KErrNone || aOverrideError) sl@0: { sl@0: iError = aError; sl@0: } sl@0: sl@0: iObserver.MfaocComplete(iError, iCurrentConfig->iController, iCurrentConfig->iControllerUid, &iSourceHandle, &iSinkHandle); sl@0: sl@0: // if we've just attempted to open the Secondary controller, sl@0: // try to open the Primary controller sl@0: if (iCurrentConfig == iSecondaryConfig) sl@0: { sl@0: if (iError == KErrNone) sl@0: OpenPrimaryController(); sl@0: } sl@0: sl@0: // if we failed to open, may as well free up some memory sl@0: // if open succeeded we need to preserve state in case of a re-open sl@0: if (iError != KErrNone) sl@0: { sl@0: if(iControllerIndex >= iControllerCount-1) sl@0: { sl@0: Close(); sl@0: } sl@0: else //if there are other controllers selected in the controller list, try them sl@0: { sl@0: Cancel(); sl@0: if(iAddDataSourceSinkAsync) sl@0: { sl@0: iAddDataSourceSinkAsync->Cancel(); sl@0: } sl@0: sl@0: TryNextController(); sl@0: } sl@0: } sl@0: } sl@0: sl@0: void CMMFFindAndOpenController::SchedSendError(TInt aError) sl@0: { sl@0: if (aError != KErrNone) sl@0: iError = aError; sl@0: iState = ESendError; sl@0: KickState(); sl@0: } sl@0: sl@0: void CMMFFindAndOpenController::BuildControllerListFileNameL() sl@0: { sl@0: // Retrieve a list of possible controllers from ECOM sl@0: // If we don't have a match, leave with unsupported sl@0: sl@0: iControllers.ResetAndDestroy(); sl@0: iPrioritisedControllers.Reset(); sl@0: sl@0: TControllerMode mode = iCurrentConfig->iControllerMode; sl@0: sl@0: // if we're playing, try to get the MIME type from the Content Access sl@0: // Framework (CAF) & use that to select a controller - if that fails, sl@0: // try to select a controller based on the header data/file extension sl@0: sl@0: CMMFUtilityFileInfo* fileInfo = NULL; sl@0: sl@0: TInt error; sl@0: sl@0: //If the current CMMSourceSink is a CMMFileSourceSink sl@0: // Using the previous version we'd get KErrCANoPermission when calling EvaluateIntent in the sl@0: // CMMFUtilityFileInfo ConstructL as the intent == EUnknown, so now pass the intent as a parameter sl@0: // to TMMFileHandleSource and.... sl@0: TBool isSecureDrmProcess = EFalse; sl@0: //need to do this only in local playback mode sl@0: //UseSecureDRMProcess() function in called only in case of local play / record sl@0: // so we'll just chk for playback mode sl@0: if(mode == EPlayback) sl@0: { sl@0: TRAP(error, UseSecureDRMProcessL(isSecureDrmProcess)); sl@0: if(error == KErrPermissionDenied) sl@0: { sl@0: isSecureDrmProcess = ETrue; sl@0: } sl@0: else sl@0: { sl@0: User::LeaveIfError(error); sl@0: } sl@0: } sl@0: TRAP(error, fileInfo = CreateFileInfoL(isSecureDrmProcess)); sl@0: sl@0: if (fileInfo != NULL) sl@0: { sl@0: CleanupDeletePushL(fileInfo); sl@0: } sl@0: sl@0: if (error != KErrNone) sl@0: { sl@0: // if playback mode, leave for any error sl@0: // if record mode, allow KErrNotFound sl@0: if (mode == EPlayback || (mode != EPlayback && error != KErrNotFound)) sl@0: { sl@0: User::Leave(error); sl@0: } sl@0: } sl@0: sl@0: CMMFControllerPluginSelectionParameters* cSelect = NULL; sl@0: if (isSecureDrmProcess) sl@0: { sl@0: cSelect = CMMFControllerSecureDrmPluginSelectionParameters::NewLC(); sl@0: } sl@0: else sl@0: { sl@0: cSelect = CMMFControllerPluginSelectionParameters::NewLC(); sl@0: } sl@0: RArray mediaIds; sl@0: CleanupClosePushL(mediaIds); sl@0: User::LeaveIfError(mediaIds.Append(iMediaId)); sl@0: sl@0: cSelect->SetMediaIdsL(mediaIds, iMediaIdMatchType); sl@0: sl@0: if (mode == EPlayback) sl@0: { sl@0: ASSERT(fileInfo!=NULL); sl@0: TBuf8 mimeType; sl@0: TBool mimeTypeKnown = fileInfo->GetFileMimeTypeL(mimeType); sl@0: if (mimeTypeKnown) sl@0: { sl@0: CMMFFormatSelectionParameters* fSelect = CMMFFormatSelectionParameters::NewLC(); sl@0: fSelect->SetMatchToMimeTypeL(mimeType); sl@0: cSelect->SetRequiredPlayFormatSupportL(*fSelect); sl@0: cSelect->ListImplementationsL(iControllers); sl@0: CleanupStack::PopAndDestroy(fSelect); sl@0: } sl@0: sl@0: sl@0: // copy to the iPrioritisedControllers array - this is a NOOP if the sl@0: // MIME type is not known since iControllers will be empty sl@0: ASSERT(mimeTypeKnown || iControllers.Count() == 0); sl@0: for (TInt controllerIndex=0; controllerIndex < iControllers.Count(); controllerIndex++) sl@0: User::LeaveIfError(iPrioritisedControllers.Append(iControllers[controllerIndex])); sl@0: sl@0: iControllerCount = iPrioritisedControllers.Count(); sl@0: if (iControllerCount > 0) sl@0: { sl@0: // Clean up sl@0: // cSelect, mediaIds, sl@0: CleanupStack::PopAndDestroy(2, cSelect); sl@0: if (fileInfo != NULL) sl@0: { sl@0: CleanupStack::PopAndDestroy(fileInfo); sl@0: } sl@0: return; sl@0: } sl@0: } sl@0: sl@0: // Retrieve header data first. If file doesn't exist, its ok. sl@0: HBufC8* headerData = HBufC8::NewLC(KMaxHeaderSize); sl@0: TPtr8 headerDataPtr = headerData->Des(); sl@0: if (fileInfo) sl@0: { sl@0: fileInfo->GetFileHeaderDataL(headerDataPtr, KMaxHeaderSize); sl@0: } sl@0: sl@0: // Get the filename's suffix sl@0: HBufC8* fileSuffix = CMMFClientUtility::GetFileExtensionL(iFileName); sl@0: sl@0: CleanupStack::PushL(fileSuffix); sl@0: TPtr8 fileSuffixPtr = fileSuffix->Des(); sl@0: sl@0: // Get the secondary filename's header data (for convert) sl@0: HBufC8* headerDataSecondary = HBufC8::NewLC(KMaxHeaderSize); sl@0: TPtr8 headerDataPtrSecondary = headerDataSecondary->Des(); sl@0: if (iFileNameSecondary.Length() > 0 && fileInfo) sl@0: { sl@0: fileInfo->GetFileHeaderDataL(headerDataPtrSecondary, KMaxHeaderSize); sl@0: } sl@0: sl@0: // Get the secondary filename's suffix sl@0: HBufC8* fileSuffixSecondary = CMMFClientUtility::GetFileExtensionL(iFileNameSecondary); sl@0: CleanupStack::PushL(fileSuffixSecondary); sl@0: TPtr8 fileSuffixPtrSecondary = fileSuffixSecondary->Des(); sl@0: sl@0: sl@0: CMMFFormatSelectionParameters* fSelect = CMMFFormatSelectionParameters::NewLC(); sl@0: sl@0: if (mode == EPlayback || mode == EConvert) sl@0: cSelect->SetRequiredPlayFormatSupportL(*fSelect); sl@0: if (mode == ERecord || mode == EConvert) sl@0: cSelect->SetRequiredRecordFormatSupportL(*fSelect); sl@0: sl@0: cSelect->ListImplementationsL(iControllers); sl@0: sl@0: if (iControllers.Count()==0) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: if (mode == ERecord) sl@0: { sl@0: CMMFClientUtility::PrioritiseControllersL( sl@0: iControllers, sl@0: headerDataPtrSecondary, sl@0: fileSuffixPtrSecondary, sl@0: headerDataPtr, sl@0: fileSuffixPtr, sl@0: iPrioritisedControllers); sl@0: } sl@0: else sl@0: { sl@0: CMMFClientUtility::PrioritiseControllersL( sl@0: iControllers, sl@0: headerDataPtr, sl@0: fileSuffixPtr, sl@0: headerDataPtrSecondary, sl@0: fileSuffixPtrSecondary, sl@0: iPrioritisedControllers); sl@0: } sl@0: sl@0: iControllerCount = iPrioritisedControllers.Count(); sl@0: if (iControllerCount == 0) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: // Clean up sl@0: // cSelect, mediaIds, sl@0: // headerData, fileSuffix, headerDataSecondary, fileSuffixSecondary, sl@0: // fSelect sl@0: CleanupStack::PopAndDestroy(7, cSelect); sl@0: if (fileInfo != NULL) sl@0: { sl@0: CleanupStack::PopAndDestroy(fileInfo); sl@0: } sl@0: } sl@0: sl@0: void CMMFFindAndOpenController::BuildControllerListDescriptorL() sl@0: { sl@0: // Retrieve a list of possible controllers from ECOM sl@0: // If we don't have a match, leave with unsupported sl@0: sl@0: iControllers.ResetAndDestroy(); sl@0: sl@0: CMMFControllerPluginSelectionParameters* cSelect = CMMFControllerPluginSelectionParameters::NewLC(); sl@0: CMMFFormatSelectionParameters* fSelect = CMMFFormatSelectionParameters::NewLC(); sl@0: sl@0: sl@0: RArray mediaIds; sl@0: CleanupClosePushL(mediaIds); sl@0: User::LeaveIfError(mediaIds.Append(iMediaId)); sl@0: sl@0: cSelect->SetMediaIdsL(mediaIds, iMediaIdMatchType); sl@0: sl@0: TPtrC8 header = iDescriptor.Left(KMaxHeaderSize); sl@0: fSelect->SetMatchToHeaderDataL(header); sl@0: sl@0: sl@0: TControllerMode mode = iCurrentConfig->iControllerMode; sl@0: if (mode == EPlayback || mode == EConvert) sl@0: cSelect->SetRequiredPlayFormatSupportL(*fSelect); sl@0: if (mode == ERecord || mode == EConvert) sl@0: cSelect->SetRequiredRecordFormatSupportL(*fSelect); sl@0: sl@0: cSelect->ListImplementationsL(iControllers); sl@0: sl@0: iControllerCount = iControllers.Count(); sl@0: if (iControllerCount == 0) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: // Clean up sl@0: // cSelect, fSelect, mediaIds sl@0: CleanupStack::PopAndDestroy(3, cSelect); sl@0: } sl@0: sl@0: void CMMFFindAndOpenController::BuildControllerListUrlL() sl@0: { sl@0: // Retrieve a list of possible controllers from ECOM sl@0: // If we don't have a match, leave with unsupported sl@0: sl@0: iControllers.ResetAndDestroy(); sl@0: sl@0: CMMFControllerPluginSelectionParameters* cSelect = CMMFControllerPluginSelectionParameters::NewLC(); sl@0: CMMFFormatSelectionParameters* fSelect = CMMFFormatSelectionParameters::NewLC(); sl@0: sl@0: RArray mediaIds; sl@0: CleanupClosePushL(mediaIds); sl@0: User::LeaveIfError(mediaIds.Append(iMediaId)); sl@0: sl@0: cSelect->SetMediaIdsL(mediaIds, iMediaIdMatchType); sl@0: sl@0: sl@0: if (*iMimeType != KNullDesC8) sl@0: { sl@0: fSelect->SetMatchToMimeTypeL(*iMimeType);//We match to mime type sl@0: } sl@0: else sl@0: { sl@0: fSelect->SetMatchToUriSupportL(*iUrl); sl@0: } sl@0: sl@0: TControllerMode mode = iCurrentConfig->iControllerMode; sl@0: if (mode == EPlayback || mode == EConvert) sl@0: cSelect->SetRequiredPlayFormatSupportL(*fSelect); sl@0: if (mode == ERecord || mode == EConvert) sl@0: cSelect->SetRequiredRecordFormatSupportL(*fSelect); sl@0: sl@0: cSelect->ListImplementationsL(iControllers); sl@0: sl@0: iControllerCount = iControllers.Count(); sl@0: if (iControllerCount == 0) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: // Clean up sl@0: // cSelect, fSelect, mediaIds sl@0: CleanupStack::PopAndDestroy(3, cSelect); sl@0: } sl@0: sl@0: void CMMFFindAndOpenController::BuildControllerListFormatL() sl@0: { sl@0: // Retrieve a list of possible controllers from ECOM sl@0: // If we don't have a match, leave with unsupported sl@0: sl@0: iControllers.ResetAndDestroy(); sl@0: iPrioritisedControllers.Reset(); sl@0: sl@0: CMMFControllerPluginSelectionParameters* cSelect = CMMFControllerPluginSelectionParameters::NewLC(); sl@0: sl@0: // Select the media IDs to allow sl@0: RArray mediaIds; sl@0: CleanupClosePushL(mediaIds); sl@0: User::LeaveIfError(mediaIds.Append(iMediaId)); sl@0: sl@0: cSelect->SetMediaIdsL(mediaIds, iMediaIdMatchType); sl@0: sl@0: CMMFFormatSelectionParameters* fSelect = CMMFFormatSelectionParameters::NewLC(); sl@0: sl@0: TControllerMode mode = iCurrentConfig->iControllerMode; sl@0: if (mode == EPlayback || mode == EConvert) sl@0: cSelect->SetRequiredPlayFormatSupportL(*fSelect); sl@0: if (mode == ERecord || mode == EConvert) sl@0: cSelect->SetRequiredRecordFormatSupportL(*fSelect); sl@0: sl@0: //Obtain a list of the controllers sl@0: cSelect->ListImplementationsL(iControllers); sl@0: sl@0: CleanupStack::PopAndDestroy(3, cSelect); // cSelect, mediaIds, fSelect sl@0: sl@0: iControllerCount = iControllers.Count(); sl@0: if (iControllerCount == 0) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: TUid formatUidPrimary; sl@0: TUid formatUidSecondary; sl@0: if (mode == ERecord) sl@0: { sl@0: formatUidSecondary = iFormatUid; sl@0: formatUidPrimary = iFormatUidSecondary; sl@0: } sl@0: else sl@0: { sl@0: formatUidPrimary = iFormatUid; sl@0: formatUidSecondary = iFormatUidSecondary; sl@0: } sl@0: sl@0: for (TInt controllerIndex=0; controllerIndex < iControllers.Count(); controllerIndex++) sl@0: { sl@0: const RMMFFormatImplInfoArray& recFormatInfo = iControllers[controllerIndex]->RecordFormats(); sl@0: const RMMFFormatImplInfoArray& playFormatInfo = iControllers[controllerIndex]->PlayFormats(); sl@0: sl@0: TBool playFormatMatched = EFalse; sl@0: TBool recordFormatMatched = EFalse; sl@0: sl@0: if (formatUidPrimary == KNullUid) sl@0: { sl@0: playFormatMatched = ETrue; sl@0: } sl@0: else sl@0: { sl@0: for(TInt playFormatIndex =0; playFormatIndex < playFormatInfo.Count(); playFormatIndex++) sl@0: { sl@0: if(playFormatInfo[playFormatIndex]->Uid() == formatUidPrimary) sl@0: { sl@0: playFormatMatched = ETrue; sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: sl@0: if (formatUidSecondary == KNullUid) sl@0: { sl@0: recordFormatMatched = ETrue; sl@0: } sl@0: else sl@0: { sl@0: for (TInt recFormatIndex =0; recFormatIndex < recFormatInfo.Count(); recFormatIndex++) sl@0: { sl@0: if (recFormatInfo[recFormatIndex]->Uid() == formatUidSecondary) sl@0: { sl@0: recordFormatMatched = ETrue; sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: sl@0: if (playFormatMatched && recordFormatMatched) sl@0: User::LeaveIfError(iPrioritisedControllers.Append(iControllers[controllerIndex])); sl@0: } sl@0: sl@0: iControllerCount = iPrioritisedControllers.Count(); sl@0: if (iControllerCount == 0) sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: CMMSourceSink* CMMFFindAndOpenController::CreateSourceSinkL(const TSourceSink& aParams) sl@0: { sl@0: if (aParams.iUseFileHandle) sl@0: { sl@0: return CMMFileSourceSink::NewL(aParams.iUid, aParams.iFileHandle); sl@0: } sl@0: return CMMSourceSink::NewL(aParams.iUid, aParams.iConfigData); sl@0: } sl@0: sl@0: sl@0: CMMSourceSink* CMMFFindAndOpenController::CreateSourceSinkL(const TMMSource& aSource) sl@0: { sl@0: if (!(aSource.SourceType()==KUidMMFileSource || sl@0: aSource.SourceType()==KUidMMFileHandleSource)) sl@0: User::Leave(KErrNotSupported); sl@0: sl@0: return CMMFileSourceSink::NewL(KUidMmfFileSource, aSource); sl@0: } sl@0: sl@0: CMMFUtilityFileInfo* CMMFFindAndOpenController::CreateFileInfoL(TBool aSecureDRMMode) sl@0: { sl@0: CMMFUtilityFileInfo* fileInfo = NULL; sl@0: if (iUseFileHandle) sl@0: { sl@0: if (iUniqueId != NULL) sl@0: { sl@0: TMMFileHandleSource fileHandleSource(iFileHandle, (*iUniqueId), iIntent,iEnableUi); sl@0: fileInfo = CMMFUtilityFileInfo::NewL(fileHandleSource, aSecureDRMMode); sl@0: } sl@0: else sl@0: { sl@0: TMMFileHandleSource fileHandleSource(iFileHandle); sl@0: fileInfo = CMMFUtilityFileInfo::NewL(fileHandleSource, aSecureDRMMode); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: if (iUniqueId != NULL) sl@0: { sl@0: TMMFileSource fileSource(iFileName, (*iUniqueId), iIntent,iEnableUi); sl@0: fileInfo = CMMFUtilityFileInfo::NewL(fileSource, aSecureDRMMode); sl@0: } sl@0: else sl@0: { sl@0: TMMFileSource fileSource(iFileName); sl@0: fileInfo = CMMFUtilityFileInfo::NewL(fileSource, aSecureDRMMode); sl@0: } sl@0: } sl@0: return fileInfo; sl@0: } sl@0: sl@0: EXPORT_C CMMFFindAndOpenController::TSourceSink::TSourceSink(TUid aUid, const TDesC8& aConfigData) sl@0: : iConfigData(aConfigData) sl@0: { sl@0: iUid = aUid; sl@0: sl@0: iUseFileHandle = EFalse; sl@0: } sl@0: sl@0: EXPORT_C CMMFFindAndOpenController::TSourceSink::TSourceSink(TUid aUid, const RFile& aFile) sl@0: : iConfigData(KNullDesC8) sl@0: { sl@0: iUid = aUid; sl@0: sl@0: iFileHandle = aFile; sl@0: iUseFileHandle = ETrue; sl@0: } sl@0: sl@0: EXPORT_C void CMMFFindAndOpenController::SetInitScreenNumber(TInt aScreenNumber, RMMFVideoSetInitScreenCustomCommands* aVideoSetInitScreenCustomCommands) sl@0: { sl@0: iScreenNumber = aScreenNumber; sl@0: iVideoSetInitScreenCustomCommands = aVideoSetInitScreenCustomCommands; sl@0: } sl@0: sl@0: CMMFFindAndOpenController::CConfig::CConfig() sl@0: { sl@0: } sl@0: sl@0: void CMMFFindAndOpenController::CConfig::Close() sl@0: { sl@0: delete iSource; sl@0: iSource = NULL; sl@0: delete iSink; sl@0: iSink = NULL; sl@0: } sl@0: CMMFFindAndOpenController::CConfig::~CConfig() sl@0: { sl@0: Close(); sl@0: } sl@0: sl@0: void CMMFFindAndOpenController::UseSecureDRMProcessL(TBool& aIsSecureDrmProcess) sl@0: { sl@0: if(iHasDrmCapability)//if client has DRM capability, we never use Secure DRM Process sl@0: { sl@0: aIsSecureDrmProcess = EFalse; sl@0: return; sl@0: } sl@0: TBool isDataProtected = EFalse; sl@0: ContentAccess::CContent* content = NULL; sl@0: TControllerMode mode = iCurrentConfig->iControllerMode; sl@0: sl@0: //setting aUseSecureDrmProcess to false(default value) sl@0: aIsSecureDrmProcess = EFalse; sl@0: sl@0: //need to proceed only in case of local playback mode sl@0: TUid sourceUid = iCurrentConfig->iSource->SourceSinkUid(); sl@0: TBool localPlaybackMode = ( mode == EPlayback && sl@0: (sourceUid == KUidMmfFileSource || sourceUid == KUidMmfDescriptorSource) ); sl@0: if(!localPlaybackMode) sl@0: { sl@0: return; sl@0: } sl@0: sl@0: if (iUseFileHandle && iOwnFileHandle) sl@0: { sl@0: content = ContentAccess::CContent::NewLC(iFileHandle); sl@0: } sl@0: else if(iFileName.Length()) //need to check if file name exist sl@0: { sl@0: content = ContentAccess::CContent::NewLC(iFileName); sl@0: } sl@0: else sl@0: {//in case of descriptor source content object will not be created sl@0: return; sl@0: } sl@0: TInt value = 0; sl@0: TInt error = KErrNone; sl@0: if(iUniqueId != NULL) sl@0: { sl@0: error = content->GetAttribute(EIsProtected, value, *iUniqueId ); sl@0: } sl@0: else sl@0: { sl@0: error = content->GetAttribute(EIsProtected, value); sl@0: } sl@0: if( (error == KErrNone && value) || error == KErrPermissionDenied ) sl@0: {//2nd condition can be true if GetAttribute checks for DRM cap and return error if not found sl@0: isDataProtected = ETrue; sl@0: } sl@0: else if( error != KErrNone && error != KErrPermissionDenied) sl@0: {//leaving as GetAttribute of CAF caused an error. sl@0: User::Leave(error); sl@0: } sl@0: sl@0: CleanupStack::PopAndDestroy(content); sl@0: if(isDataProtected && !iHasDrmCapability && mode == EPlayback) sl@0: {//only when the Data is protected and client does not have the DRM capability, we need secure DRM process sl@0: aIsSecureDrmProcess = ETrue; sl@0: } sl@0: } sl@0: sl@0: EXPORT_C CMMSourceSink* CMMSourceSink::NewLC(TUid aUid, const TDesC8& aDescriptor) sl@0: { sl@0: CMMSourceSink* self = new (ELeave) CMMSourceSink(aUid); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aDescriptor); sl@0: return self; sl@0: } sl@0: sl@0: EXPORT_C CMMSourceSink* CMMSourceSink::NewL(TUid aUid, const TDesC8& aDescriptor) sl@0: { sl@0: CMMSourceSink* sourcesink = CMMSourceSink::NewLC(aUid, aDescriptor); sl@0: CleanupStack::Pop(sourcesink); sl@0: return sourcesink; sl@0: } sl@0: sl@0: CMMSourceSink::CMMSourceSink(TUid aUid) sl@0: : iUid(aUid) sl@0: { sl@0: } sl@0: sl@0: CMMSourceSink::~CMMSourceSink() sl@0: { sl@0: delete iBuf; sl@0: } sl@0: sl@0: void CMMSourceSink::ConstructL(const TDesC8& aDescriptor) sl@0: { sl@0: iBuf = aDescriptor.AllocL(); sl@0: } sl@0: sl@0: TUid CMMSourceSink::SourceSinkUid() const sl@0: { sl@0: return iUid; sl@0: } sl@0: sl@0: const TDesC8& CMMSourceSink::SourceSinkData() const sl@0: { sl@0: return *iBuf; sl@0: } sl@0: sl@0: TBool CMMSourceSink::CarryingFileHandle() const sl@0: { sl@0: return EFalse; sl@0: } sl@0: sl@0: EXPORT_C CMMFileSourceSink* CMMFileSourceSink::NewLC(TUid aUid, const RFile& aFile) sl@0: { sl@0: CMMFileSourceSink* self = new (ELeave) CMMFileSourceSink(aUid); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aFile); sl@0: return self; sl@0: } sl@0: sl@0: EXPORT_C CMMFileSourceSink* CMMFileSourceSink::NewL(TUid aUid, const RFile& aFile) sl@0: { sl@0: CMMFileSourceSink* sourcesink = CMMFileSourceSink::NewLC(aUid, aFile); sl@0: CleanupStack::Pop(sourcesink); sl@0: return sourcesink; sl@0: } sl@0: sl@0: CMMFileSourceSink::CMMFileSourceSink(TUid aUid) sl@0: : CMMSourceSink(aUid) sl@0: { sl@0: } sl@0: sl@0: void CMMFileSourceSink::ConstructL(const RFile& aFile) sl@0: { sl@0: User::LeaveIfError(iHandle.Duplicate(aFile)); sl@0: iUsingFileHandle = ETrue; sl@0: iFileName = HBufC::NewMaxL(KMaxFileName); sl@0: TPtr fileNamePtr = iFileName->Des(); sl@0: iHandle.Name(fileNamePtr); sl@0: DoCreateFileHandleSourceConfigDataL(); sl@0: } sl@0: sl@0: void CMMFileSourceSink::DoCreateFileHandleSourceConfigDataL() sl@0: { sl@0: CBufFlat* buf = CBufFlat::NewL(KExpandSize); sl@0: CleanupStack::PushL(buf); sl@0: RBufWriteStream stream; sl@0: stream.Open(*buf); sl@0: CleanupClosePushL(stream); sl@0: sl@0: TPckgBuf fileptr(&iHandle); sl@0: stream.WriteInt32L(KMMFileHandleSourceUid.iUid); sl@0: stream.WriteL(fileptr); sl@0: sl@0: TInt length = 0; sl@0: if (iUniqueId != NULL) sl@0: length = iUniqueId->Length(); sl@0: stream.WriteInt32L(length); sl@0: if (length>0) sl@0: stream.WriteL(*iUniqueId); sl@0: sl@0: stream.WriteInt32L(iEnableUI); sl@0: sl@0: stream.CommitL(); sl@0: CleanupStack::PopAndDestroy(&stream); sl@0: iSourceSinkData = buf->Ptr(0).AllocL(); sl@0: sl@0: CleanupStack::PopAndDestroy(buf); sl@0: } sl@0: sl@0: const TDesC8& CMMFileSourceSink::SourceSinkData() const sl@0: { sl@0: ASSERT(iSourceSinkData); sl@0: return *iSourceSinkData; sl@0: } sl@0: sl@0: CMMFileSourceSink::~CMMFileSourceSink() sl@0: { sl@0: iHandle.Close(); // delete whatever sl@0: delete iFileName; sl@0: delete iSourceSinkData; sl@0: delete iUniqueId; sl@0: } sl@0: sl@0: EXPORT_C CMMFileSourceSink* CMMFileSourceSink::NewLC(TUid aUid, const TMMSource& aSource) sl@0: { sl@0: CMMFileSourceSink* self = new (ELeave) CMMFileSourceSink(aUid); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aSource); sl@0: return self; sl@0: } sl@0: sl@0: EXPORT_C CMMFileSourceSink* CMMFileSourceSink::NewL(TUid aUid, const TMMSource& aSource) sl@0: { sl@0: CMMFileSourceSink* sourcesink = CMMFileSourceSink::NewLC(aUid, aSource); sl@0: CleanupStack::Pop(sourcesink); sl@0: return sourcesink; sl@0: } sl@0: sl@0: void CMMFileSourceSink::ConstructL(const TMMSource& aSource) sl@0: { sl@0: iUniqueId = aSource.UniqueId().AllocL(); sl@0: iIntent = aSource.Intent(); sl@0: iEnableUI = aSource.IsUIEnabled(); sl@0: sl@0: if (aSource.SourceType() == KUidMMFileSource) sl@0: { sl@0: const TMMFileSource& fileSource = static_cast(aSource); sl@0: iFileName = fileSource.Name().AllocL(); sl@0: sl@0: DoCreateFileSourceConfigDataL(); sl@0: } sl@0: else if (aSource.SourceType() == KUidMMFileHandleSource) sl@0: { sl@0: const TMMFileHandleSource& fileHandleSource = static_cast(aSource); sl@0: iHandle.Close(); // in case already open sl@0: User::LeaveIfError(iHandle.Duplicate(fileHandleSource.Handle())); sl@0: iUsingFileHandle = ETrue; sl@0: iFileName = HBufC::NewMaxL(KMaxFileName); sl@0: TPtr fileNamePtr = iFileName->Des(); sl@0: iHandle.Name(fileNamePtr); sl@0: sl@0: DoCreateFileHandleSourceConfigDataL(); sl@0: } sl@0: else sl@0: { sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: } sl@0: sl@0: void CMMSourceSink::EvaluateIntentL() sl@0: { sl@0: } sl@0: sl@0: void CMMFileSourceSink::EvaluateIntentL() sl@0: { sl@0: if (iUsingFileHandle) sl@0: { sl@0: ContentAccess::CContent* Content = ContentAccess::CContent::NewLC(iHandle); sl@0: Content->OpenContentLC(iIntent, *iUniqueId); sl@0: CleanupStack::PopAndDestroy(2, Content); sl@0: } sl@0: else sl@0: { sl@0: ContentAccess::CContent* Content = ContentAccess::CContent::NewLC(*iFileName); sl@0: Content->OpenContentLC(iIntent, *iUniqueId); sl@0: CleanupStack::PopAndDestroy(2, Content); sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: EXPORT_C void CMMFileSourceSink::EvaluateIntentL(ContentAccess::TIntent aIntent) sl@0: { sl@0: if (iUsingFileHandle) sl@0: { sl@0: ContentAccess::CContent* Content = ContentAccess::CContent::NewLC(iHandle); sl@0: Content->OpenContentLC(aIntent, *iUniqueId); sl@0: CleanupStack::PopAndDestroy(2, Content); sl@0: } sl@0: else sl@0: { sl@0: ContentAccess::CContent* Content = ContentAccess::CContent::NewLC(*iFileName); sl@0: Content->OpenContentLC(aIntent, *iUniqueId); sl@0: CleanupStack::PopAndDestroy(2, Content); sl@0: } sl@0: } sl@0: sl@0: void CMMFileSourceSink::DoCreateFileSourceConfigDataL() sl@0: { sl@0: CBufFlat* buf = CBufFlat::NewL(KExpandSize); sl@0: CleanupStack::PushL(buf); sl@0: RBufWriteStream stream; sl@0: stream.Open(*buf); sl@0: CleanupClosePushL(stream); sl@0: sl@0: stream.WriteInt32L(KMMFileSourceUid.iUid); sl@0: stream.WriteInt32L(iFileName->Length()); sl@0: stream.WriteL(*iFileName); sl@0: TInt length = 0; sl@0: if (iUniqueId != NULL) sl@0: length = iUniqueId->Length(); sl@0: stream.WriteInt32L(length); sl@0: if (length>0) sl@0: stream.WriteL(*iUniqueId); sl@0: sl@0: stream.WriteInt32L(iEnableUI); sl@0: sl@0: stream.CommitL(); sl@0: CleanupStack::PopAndDestroy(&stream); sl@0: iSourceSinkData = buf->Ptr(0).AllocL(); sl@0: sl@0: CleanupStack::PopAndDestroy(buf); sl@0: } sl@0: sl@0: TBool CMMFileSourceSink::CarryingFileHandle() const sl@0: { sl@0: return iUsingFileHandle; sl@0: } sl@0: sl@0: