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: // sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS sl@0: #include sl@0: #include sl@0: #endif sl@0: sl@0: inline void ExtendedDataTlsCleanup(TAny* /*aPtr*/) sl@0: { sl@0: delete static_cast(Dll::Tls()); sl@0: Dll::SetTls(NULL); sl@0: } sl@0: sl@0: CMMFController* CMMFController::NewL(TUid aControllerUid, MAsyncEventHandler& aEventHandler, TThreadId aClientTid) sl@0: { sl@0: Dll::SetTls(CMMFController::CreateExtendedDataL(aClientTid)); sl@0: CleanupStack::PushL(TCleanupItem(&ExtendedDataTlsCleanup, NULL)); sl@0: CMMFController* s = REINTERPRET_CAST(CMMFController*,REComSession::CreateImplementationL(aControllerUid,_FOFF(CMMFController,iDtor_ID_Key))); sl@0: CleanupStack::PushL(s); sl@0: s->ConstructL(aEventHandler, aClientTid); sl@0: CleanupStack::Pop(s); sl@0: CleanupStack::PopAndDestroy(); // TCleanupItem(ExtendedDataTlsCleanup) sl@0: return s; sl@0: } sl@0: sl@0: void CMMFController::ConstructL(MAsyncEventHandler& aEventHandler, TThreadId aClientTid) sl@0: { sl@0: iAsyncEventHandler = &aEventHandler; sl@0: sl@0: // If extended data hasn't been initialized, GetExtendedDataL will initialize it and sl@0: // add it into iMMFObjectContainer sl@0: #ifdef _DEBUG sl@0: CMMFControllerExtendedData* extendData = sl@0: #endif sl@0: GetExtendedDataL(); sl@0: #ifdef _DEBUG sl@0: ASSERT(extendData->ClientThreadId() == aClientTid); sl@0: #else sl@0: (void)aClientTid; // remove compilation error sl@0: #endif sl@0: } sl@0: sl@0: EXPORT_C CMMFController::~CMMFController() sl@0: { sl@0: delete iCustomCommandParserManager; sl@0: delete iMMFObjectContainer; sl@0: delete iMetaDataBuffer; sl@0: REComSession::DestroyedImplementation(iDtor_ID_Key); sl@0: } sl@0: sl@0: EXPORT_C TInt CMMFController::DoSendEventToClient(const TMMFEvent& aEvent) sl@0: { sl@0: return iAsyncEventHandler->SendEventToClient(aEvent); sl@0: } sl@0: sl@0: EXPORT_C CMMFObjectContainer& CMMFController::MMFObjectContainerL() sl@0: { sl@0: // Construct iMMFObjectContainer if we haven't already. sl@0: if (!iMMFObjectContainer) sl@0: iMMFObjectContainer = new(ELeave) CMMFObjectContainer; sl@0: return *iMMFObjectContainer; sl@0: } sl@0: sl@0: EXPORT_C void CMMFController::AddCustomCommandParserL(CMMFCustomCommandParserBase& aParser) sl@0: { sl@0: // Construct iCustomCommandParserManager if we haven't already sl@0: if (!iCustomCommandParserManager) sl@0: iCustomCommandParserManager = CMMFCustomCommandParserManager::NewL(); sl@0: iCustomCommandParserManager->AddCustomCommandParserL(aParser); sl@0: } sl@0: sl@0: sl@0: EXPORT_C void CMMFController::HandleRequestL(TMMFMessage& aMessage) sl@0: { sl@0: // If the message has the constant controller destination handle, pass the message to sl@0: // the controller plugin to handle. sl@0: // Otherwise, the message must be for one of the MMFObjects. sl@0: if (aMessage.Destination().DestinationHandle() == KMMFObjectHandleController) sl@0: { sl@0: // If the message has an interface ID for this controller, handle it here. sl@0: // Otherwise, pass it to the controller plugin to handle as a custom command. sl@0: if (aMessage.Destination().InterfaceId() == KUidInterfaceMMFController) sl@0: { sl@0: TBool complete = ETrue; sl@0: switch (aMessage.Function()) sl@0: { sl@0: case EMMFControllerAddDataSource: sl@0: complete = DoAddDataSourceL(aMessage); sl@0: break; sl@0: case EMMFControllerAddDataSink: sl@0: complete = DoAddDataSinkL(aMessage); sl@0: break; sl@0: case EMMFControllerRemoveDataSource: sl@0: complete = DoRemoveDataSourceL(aMessage); sl@0: break; sl@0: case EMMFControllerRemoveDataSink: sl@0: complete = DoRemoveDataSinkL(aMessage); sl@0: break; sl@0: case EMMFControllerReset: sl@0: complete = DoResetL(aMessage); sl@0: break; sl@0: case EMMFControllerPrime: sl@0: complete = DoPrimeL(aMessage); sl@0: break; sl@0: case EMMFControllerPlay: sl@0: complete = DoPlayL(aMessage); sl@0: break; sl@0: case EMMFControllerPause: sl@0: complete = DoPauseL(aMessage); sl@0: break; sl@0: case EMMFControllerStop: sl@0: complete = DoStopL(aMessage); sl@0: break; sl@0: case EMMFControllerGetPosition: sl@0: complete = DoGetPositionL(aMessage); sl@0: break; sl@0: case EMMFControllerSetPosition: sl@0: complete = DoSetPositionL(aMessage); sl@0: break; sl@0: case EMMFControllerGetDuration: sl@0: complete = DoGetDurationL(aMessage); sl@0: break; sl@0: case EMMFControllerGetNumberOfMetaDataEntries: sl@0: complete = DoGetNumberOfMetaDataEntriesL(aMessage); sl@0: break; sl@0: case EMMFControllerGetSizeOfMetaDataEntry: sl@0: complete = DoGetSizeOfMetaDataEntryL(aMessage); sl@0: break; sl@0: case EMMFControllerGetMetaDataEntry: sl@0: complete = DoGetMetaDataEntryL(aMessage); sl@0: break; sl@0: case EMMFControllerSetPrioritySettings: sl@0: complete = DoSetPrioritySettingsL(aMessage); sl@0: break; sl@0: case EMMFControllerCancelAddDataSource: sl@0: complete = ETrue;//Nothing to cancel since AddDataSource is synchronous server-side sl@0: break; sl@0: case EMMFControllerCancelAddDataSink: sl@0: complete = ETrue;//Nothing to cancel since AddDataSink is synchronous server-side sl@0: break; sl@0: case EMMFControllerAddFileHandleDataSource: sl@0: complete = DoAddFileHandleDataSourceL(aMessage); sl@0: break; sl@0: case EMMFControllerAddFileHandleDataSink: sl@0: complete = DoAddFileHandleDataSinkL(aMessage); sl@0: break; sl@0: case EMMFControllerSourceSinkInitDataPreload: sl@0: complete = DoPreloadSourceSinkInitDataL(aMessage); sl@0: break; sl@0: case EMMFControllerAddFileHandleDataSourceWithInitData: sl@0: complete = DoAddFileHandleDataSourceWithInitDataL(aMessage); sl@0: break; sl@0: case EMMFControllerAddFileHandleDataSinkWithInitData: sl@0: complete = DoAddFileHandleDataSinkWithInitDataL(aMessage); sl@0: break; sl@0: default: sl@0: User::Leave(KErrNotSupported); sl@0: break; sl@0: } sl@0: if (complete) sl@0: aMessage.Complete(KErrNone); sl@0: } sl@0: else sl@0: { sl@0: // Must be a custom command sl@0: DoCustomCommand(aMessage); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: // Message for one of the MMF Objects sl@0: CMMFObject* object = NULL; sl@0: User::LeaveIfError(MMFObjectContainerL().FindMMFObject(aMessage.Destination(), object)); sl@0: object->HandleRequest(aMessage); sl@0: } sl@0: sl@0: } sl@0: sl@0: TBool CMMFController::DoAddDataSourceL(TMMFMessage& aMessage) sl@0: { sl@0: // Get the UID of the source from the client sl@0: TMMFUidPckg uidPckg; sl@0: aMessage.ReadData1FromClientL(uidPckg); sl@0: sl@0: // Get the size of the init data and create a buffer to hold it sl@0: TInt desLength = aMessage.SizeOfData2FromClient(); sl@0: // Leaving here in order to prevent a panic in the NewLC if the value is negative sl@0: User::LeaveIfError(desLength); sl@0: HBufC8* buf = HBufC8::NewLC(desLength); sl@0: TPtr8 ptr = buf->Des(); sl@0: aMessage.ReadData2FromClientL(ptr); sl@0: sl@0: // Create the source sl@0: MDataSource* source = MDataSource::NewSourceL(uidPckg(), *buf); sl@0: CleanupStack::PopAndDestroy(buf);//buf sl@0: AddMDataSourceAndRepondClientL(source, aMessage); sl@0: sl@0: return ETrue; sl@0: } sl@0: sl@0: sl@0: TBool CMMFController::DoAddDataSinkL(TMMFMessage& aMessage) sl@0: { sl@0: // Get the UID of the sink from the client sl@0: TMMFUidPckg uidPckg; sl@0: aMessage.ReadData1FromClientL(uidPckg); sl@0: sl@0: // Get the size of the init data and create a buffer to hold it sl@0: TInt desLength = aMessage.SizeOfData2FromClient(); sl@0: // Leaving here in order to prevent a panic in the NewLC if the value is negative sl@0: User::LeaveIfError(desLength); sl@0: HBufC8* buf = HBufC8::NewLC(desLength); sl@0: TPtr8 ptr = buf->Des(); sl@0: aMessage.ReadData2FromClientL(ptr); sl@0: sl@0: // Create the sink sl@0: MDataSink* sink = MDataSink::NewSinkL(uidPckg(), *buf); sl@0: CleanupStack::PopAndDestroy(buf);//buf sl@0: AddMDataSinkAndRepondClientL(sink, aMessage); sl@0: sl@0: return ETrue; sl@0: } sl@0: sl@0: TBool CMMFController::DoRemoveDataSourceL(TMMFMessage& aMessage) sl@0: { sl@0: TMMFMessageDestinationPckg handleInfo; sl@0: aMessage.ReadData1FromClientL(handleInfo); sl@0: sl@0: // Find the correct source sl@0: CMMFObject* object = NULL; sl@0: CMMFDataSourceHolder* holder = NULL; sl@0: User::LeaveIfError(MMFObjectContainerL().FindMMFObject(handleInfo(), object)); sl@0: // Cast the object found if possible.. sl@0: if (object->Handle().InterfaceId() == KUidInterfaceMMFDataSourceHolder) sl@0: holder = STATIC_CAST(CMMFDataSourceHolder*, object); sl@0: else sl@0: User::Leave(KErrBadHandle); sl@0: sl@0: // Try to remove the data source from the plugin sl@0: RemoveDataSourceL(holder->DataSource()); sl@0: sl@0: // If we're here, the removal worked so remove the source from the object array and delete it sl@0: MMFObjectContainerL().RemoveAndDestroyMMFObject(*holder); sl@0: return ETrue; sl@0: } sl@0: sl@0: TBool CMMFController::DoRemoveDataSinkL(TMMFMessage& aMessage) sl@0: { sl@0: TMMFMessageDestinationPckg handleInfo; sl@0: aMessage.ReadData1FromClientL(handleInfo); sl@0: sl@0: // Find the correct source sl@0: CMMFObject* object = NULL; sl@0: CMMFDataSinkHolder* holder = NULL; sl@0: User::LeaveIfError(MMFObjectContainerL().FindMMFObject(handleInfo(), object)); sl@0: // Cast the object found if possible.. sl@0: if (object->Handle().InterfaceId() == KUidInterfaceMMFDataSinkHolder) sl@0: holder = STATIC_CAST(CMMFDataSinkHolder*, object); sl@0: else sl@0: User::Leave(KErrBadHandle); sl@0: sl@0: // Try to remove the data sink from the plugin sl@0: RemoveDataSinkL(holder->DataSink()); sl@0: sl@0: // If we're here, the removal worked so remove the source from the object array and delete it sl@0: MMFObjectContainerL().RemoveAndDestroyMMFObject(*holder); sl@0: return ETrue; sl@0: } sl@0: sl@0: TBool CMMFController::DoResetL(TMMFMessage& /*aMessage*/) sl@0: { sl@0: ResetL(); sl@0: // Controller extended data must be kept until the death of controller sl@0: const RPointerArray& objects = iMMFObjectContainer->MMFObjects(); sl@0: for (TInt i = objects.Count()-1; i >= 0; i--) sl@0: { sl@0: CMMFObject* object = objects[i]; sl@0: if (object->Handle().InterfaceId() != KUidMMFControllerExtendedDataHolder) sl@0: { sl@0: iMMFObjectContainer->RemoveAndDestroyMMFObject(*object); sl@0: } sl@0: } sl@0: return ETrue; sl@0: } sl@0: sl@0: TBool CMMFController::DoPrimeL(TMMFMessage& aMessage) sl@0: { sl@0: PrimeL(aMessage); sl@0: return EFalse; sl@0: } sl@0: sl@0: sl@0: EXPORT_C void CMMFController::PrimeL(TMMFMessage& aMessage) sl@0: { sl@0: PrimeL(); sl@0: aMessage.Complete(KErrNone); sl@0: } sl@0: sl@0: sl@0: TBool CMMFController::DoPlayL(TMMFMessage& aMessage) sl@0: { sl@0: PlayL(aMessage); sl@0: return EFalse; sl@0: } sl@0: sl@0: EXPORT_C void CMMFController::PlayL(TMMFMessage& aMessage) sl@0: { sl@0: PlayL(); sl@0: aMessage.Complete(KErrNone); sl@0: } sl@0: sl@0: sl@0: sl@0: TBool CMMFController::DoPauseL(TMMFMessage& aMessage) sl@0: { sl@0: PauseL(aMessage); sl@0: return EFalse; sl@0: } sl@0: sl@0: EXPORT_C void CMMFController::PauseL(TMMFMessage& aMessage) sl@0: { sl@0: PauseL(); sl@0: aMessage.Complete(KErrNone); sl@0: } sl@0: sl@0: sl@0: TBool CMMFController::DoStopL(TMMFMessage& aMessage) sl@0: { sl@0: StopL(aMessage); sl@0: return EFalse; sl@0: } sl@0: sl@0: EXPORT_C void CMMFController::StopL(TMMFMessage& aMessage) sl@0: { sl@0: StopL(); sl@0: aMessage.Complete(KErrNone); sl@0: } sl@0: sl@0: sl@0: sl@0: TBool CMMFController::DoGetPositionL(TMMFMessage& aMessage) sl@0: { sl@0: TMMFTimeIntervalMicroSecondsPckg pckg(PositionL()); sl@0: aMessage.WriteDataToClientL(pckg); sl@0: return ETrue; sl@0: } sl@0: sl@0: TBool CMMFController::DoSetPositionL(TMMFMessage& aMessage) sl@0: { sl@0: TMMFTimeIntervalMicroSecondsPckg pckg; sl@0: aMessage.ReadData1FromClientL(pckg); sl@0: SetPositionL(pckg()); sl@0: return ETrue; sl@0: } sl@0: sl@0: TBool CMMFController::DoGetDurationL(TMMFMessage& aMessage) sl@0: { sl@0: TMMFTimeIntervalMicroSecondsPckg pckg(DurationL()); sl@0: aMessage.WriteDataToClientL(pckg); sl@0: return ETrue; sl@0: } sl@0: sl@0: TBool CMMFController::DoSetPrioritySettingsL(TMMFMessage& aMessage) sl@0: { sl@0: TMMFPrioritySettingsPckg pckg; sl@0: aMessage.ReadData1FromClientL(pckg); sl@0: SetPrioritySettings(pckg()); sl@0: return ETrue; sl@0: } sl@0: sl@0: void CMMFController::DoCustomCommand(TMMFMessage& aMessage) sl@0: { sl@0: // First, try giving the message to the custom command parser manager... sl@0: TBool handled = EFalse; sl@0: if (iCustomCommandParserManager) sl@0: { sl@0: if (aMessage.Destination().InterfaceId() == KUidInterfaceMMFDRMControl || sl@0: aMessage.Destination().InterfaceId() == KUidInterfaceMMFVideoDRMExt) sl@0: { sl@0: TBool secureDrmMode = EFalse; sl@0: TRAPD(err, secureDrmMode = GetExtendedDataL()->SecureDrmMode()); sl@0: if (err) sl@0: { sl@0: aMessage.Complete(err); sl@0: handled = ETrue; sl@0: } sl@0: else if (secureDrmMode) sl@0: { sl@0: aMessage.Complete(KErrPermissionDenied); sl@0: handled = ETrue; sl@0: } sl@0: } sl@0: sl@0: if (!handled) sl@0: { sl@0: handled = iCustomCommandParserManager->HandleRequest(aMessage); sl@0: } sl@0: } sl@0: sl@0: // If the ccp manager couldn't handle the message, pass directly to the sl@0: // controller plugin as a custom command. sl@0: if (!handled) sl@0: CustomCommand(aMessage); sl@0: } sl@0: sl@0: TBool CMMFController::DoGetNumberOfMetaDataEntriesL(TMMFMessage& aMessage) sl@0: { sl@0: TInt numberOfEntries; sl@0: GetNumberOfMetaDataEntriesL(numberOfEntries); sl@0: TPckgBuf pckg(numberOfEntries); sl@0: aMessage.WriteDataToClientL(pckg); sl@0: return ETrue; sl@0: } sl@0: sl@0: TBool CMMFController::DoGetSizeOfMetaDataEntryL(TMMFMessage& aMessage) sl@0: { sl@0: // Get the index of the required entry sl@0: TPckgBuf pckg; sl@0: aMessage.ReadData1FromClientL(pckg); sl@0: // Get the entry sl@0: CMMFMetaDataEntry* entry = GetMetaDataEntryL(pckg()); sl@0: CleanupStack::PushL(entry); sl@0: // Delete any existing buffer sl@0: delete iMetaDataBuffer; sl@0: iMetaDataBuffer = NULL; sl@0: // Create a buffer to hold the externalised entry sl@0: iMetaDataBuffer = CBufFlat::NewL(32); sl@0: RBufWriteStream s; sl@0: s.Open(*iMetaDataBuffer); sl@0: CleanupClosePushL(s); sl@0: entry->ExternalizeL(s); sl@0: CleanupStack::PopAndDestroy(2);//s, entry sl@0: // Write the size of the externalised data back to the client sl@0: pckg() = iMetaDataBuffer->Ptr(0).Length(); sl@0: aMessage.WriteDataToClientL(pckg); sl@0: return ETrue; sl@0: } sl@0: sl@0: TBool CMMFController::DoGetMetaDataEntryL(TMMFMessage& aMessage) sl@0: { sl@0: // We should have already prepared the buffer sl@0: if (!iMetaDataBuffer) sl@0: User::Leave(KErrNotReady); sl@0: aMessage.WriteDataToClientL(iMetaDataBuffer->Ptr(0)); sl@0: return ETrue; sl@0: } sl@0: sl@0: TBool CMMFController::DoPreloadSourceSinkInitDataL(TMMFMessage& aMessage) sl@0: { sl@0: GetExtendedDataL()->ResetSourceSinkInitData(); sl@0: sl@0: // Get the size of the init data and create a buffer to hold it sl@0: TInt desLength = aMessage.SizeOfData1FromClient(); sl@0: HBufC8* sourceSinkInitData = HBufC8::NewLC(desLength); sl@0: TPtr8 ptr = sourceSinkInitData->Des(); sl@0: aMessage.ReadData1FromClientL(ptr); sl@0: sl@0: GetExtendedDataL()->SetSourceSinkInitData(sourceSinkInitData); sl@0: CleanupStack::Pop(sourceSinkInitData); sl@0: return ETrue; sl@0: } sl@0: sl@0: TBool CMMFController::DoAddFileHandleDataSourceWithInitDataL(TMMFMessage& aMessage) sl@0: { sl@0: if (GetExtendedDataL()->SourceSinkInitData() == NULL) sl@0: { sl@0: User::Leave(KErrNotReady); sl@0: } sl@0: HBufC8* initData = GetExtendedDataL()->SourceSinkInitData()->AllocLC(); sl@0: sl@0: // Get the client file handle and replace sl@0: RFile file; sl@0: aMessage.AdoptFileHandleFromClientL(1,2, file); sl@0: CleanupClosePushL(file); sl@0: TPtr8 initDataPtr(initData->Des()); sl@0: ReplaceFileHandleInInitDataL(&file, initDataPtr); sl@0: sl@0: // Create the source sl@0: MDataSource* source = MDataSource::NewSourceL(KUidMmfFileSource, *initData); sl@0: CleanupStack::PopAndDestroy(2, initData); //file, initData sl@0: AddMDataSourceAndRepondClientL(source, aMessage); sl@0: sl@0: GetExtendedDataL()->ResetSourceSinkInitData(); sl@0: return ETrue; sl@0: } sl@0: sl@0: TBool CMMFController::DoAddFileHandleDataSinkWithInitDataL(TMMFMessage& aMessage) sl@0: { sl@0: if (GetExtendedDataL()->SourceSinkInitData() == NULL) sl@0: { sl@0: User::Leave(KErrNotReady); sl@0: } sl@0: HBufC8* initData = GetExtendedDataL()->SourceSinkInitData()->AllocLC(); sl@0: sl@0: // Get the client file handle and replace sl@0: RFile file; sl@0: aMessage.AdoptFileHandleFromClientL(1,2, file); sl@0: CleanupClosePushL(file); sl@0: TPtr8 initDataPtr(initData->Des()); sl@0: ReplaceFileHandleInInitDataL(&file, initDataPtr); sl@0: sl@0: // Create the sink sl@0: MDataSink* sink = MDataSink::NewSinkL(KUidMmfFileSink, *initData); sl@0: CleanupStack::PopAndDestroy(2, initData); //file, initData sl@0: AddMDataSinkAndRepondClientL(sink, aMessage); sl@0: sl@0: GetExtendedDataL()->ResetSourceSinkInitData(); sl@0: return ETrue; sl@0: } sl@0: sl@0: void CMMFController::ReplaceFileHandleInInitDataL(RFile* aFile, TDes8& aInitData) sl@0: { sl@0: // aInitData should have the second 4bytes data (first 4bytes represent TUid) containing sl@0: // a client RFile pointer. sl@0: // This RFile pointer may be invalid due to the fact that client and server threads sl@0: // may reside in different processes, and therefore, different memory space. sl@0: // In this context, we would rather trust the file handle retrieve from the call sl@0: // AdoptFileHandleFromClientL, and replace the RFile pointer with a more reliable one sl@0: TPtr8 filePtrStart = aInitData.MidTPtr(sizeof(TUid)); sl@0: RDesWriteStream writeStream; sl@0: writeStream.Open(filePtrStart); sl@0: CleanupClosePushL(writeStream); sl@0: TPckgBuf filePtr(aFile); sl@0: writeStream.WriteL(filePtr); sl@0: writeStream.CommitL(); sl@0: CleanupStack::PopAndDestroy(&writeStream); sl@0: } sl@0: sl@0: void CMMFController::AddMDataSourceAndRepondClientL(MDataSource* aSource, TMMFMessage& aMessage) sl@0: { sl@0: CleanupDeletePushL(aSource); sl@0: CMMFDataSourceHolder* holder = new(ELeave) CMMFDataSourceHolder(*aSource); sl@0: CleanupStack::Pop(aSource); //aSource (since now owned by holder) sl@0: sl@0: CleanupStack::PushL(holder); sl@0: // Append holder to array of MMFObjects sl@0: User::LeaveIfError(MMFObjectContainerL().AddMMFObject(*holder)); sl@0: CleanupStack::Pop(holder);//holder sl@0: sl@0: // Write source handle info back to client sl@0: TMMFMessageDestination handleInfo(holder->Handle()); sl@0: TMMFMessageDestinationPckg handlePckg(handleInfo); sl@0: TInt error = aMessage.WriteDataToClient(handlePckg); sl@0: sl@0: // Add source to plugin sl@0: if (!error) sl@0: TRAP(error, AddDataSourceL(*aSource)); sl@0: sl@0: if (error) sl@0: { sl@0: // Source not accepted by plugin or we couldn't write handle info back to client, sl@0: // so delete it and return error to client sl@0: MMFObjectContainerL().RemoveAndDestroyMMFObject(*holder); sl@0: User::Leave(error); sl@0: } sl@0: } sl@0: sl@0: void CMMFController::AddMDataSinkAndRepondClientL(MDataSink* aSink, TMMFMessage& aMessage) sl@0: { sl@0: CleanupDeletePushL(aSink); sl@0: CMMFDataSinkHolder* holder = new(ELeave) CMMFDataSinkHolder(*aSink); sl@0: CleanupStack::Pop(aSink); //aSink (since now owned by holder) sl@0: sl@0: CleanupStack::PushL(holder); sl@0: // Append sink to array sl@0: User::LeaveIfError(MMFObjectContainerL().AddMMFObject(*holder)); sl@0: CleanupStack::Pop(holder);//holder sl@0: sl@0: // Write sink handle info back to client sl@0: TMMFMessageDestination handleInfo(holder->Handle()); sl@0: TMMFMessageDestinationPckg handlePckg(handleInfo); sl@0: TInt error = aMessage.WriteDataToClient(handlePckg); sl@0: sl@0: // Add sink to plugin sl@0: if (!error) sl@0: TRAP(error, AddDataSinkL(*aSink)); sl@0: sl@0: if (error) sl@0: { sl@0: // Sink not accepted by plugin or we couldn't write handle info back to client, sl@0: // so delete it and return error to client sl@0: MMFObjectContainerL().RemoveAndDestroyMMFObject(*holder); sl@0: User::Leave(error); sl@0: } sl@0: } sl@0: sl@0: CMMFControllerExtendedData* CMMFController::GetExtendedDataL() sl@0: { sl@0: CMMFControllerExtendedData* data = NULL; sl@0: sl@0: // iMMFObjectContainer and CMMFControllerExtendedData must be constructed sl@0: // in CMMFController constructor. Only 1 CMMFControllerExtendedData object can sl@0: // be found in iMMFObjectContainer. sl@0: const RPointerArray& objects = MMFObjectContainerL().MMFObjects(); sl@0: for (TInt i = 0; i < objects.Count(); i++) sl@0: { sl@0: if (objects[i]->Handle().InterfaceId() == KUidMMFControllerExtendedDataHolder) sl@0: { sl@0: data = static_cast(objects[i]); sl@0: break; sl@0: } sl@0: } sl@0: if (data == NULL) sl@0: { sl@0: // In this case, extended data has not been constructed and added into iMMFObjectContainer. sl@0: // This is a situation where GetExtendedDataL is being indirectly called in the controller sl@0: // initialization process (i.e. CMMFController::NewL() or constructor of licensee's controller). sl@0: // Extended data should have a copy stored in Dll::Tls already at this point. sl@0: const CMMFControllerExtendedData* dataCopy = static_cast(Dll::Tls()); sl@0: data = CreateExtendedDataL(dataCopy->ClientThreadId()); sl@0: CleanupStack::PushL(data); sl@0: User::LeaveIfError(MMFObjectContainerL().AddMMFObject(*data)); sl@0: CleanupStack::Pop(data); sl@0: } sl@0: return data; sl@0: } sl@0: sl@0: CMMFControllerExtendedData* CMMFController::CreateExtendedDataL(TThreadId aClientTid) sl@0: { sl@0: // In secureDRMMode, SecureDRM server and user are running in sl@0: // different processes. sl@0: TProcessId clientProcessId; sl@0: RThread clientThread; sl@0: CleanupClosePushL(clientThread); sl@0: User::LeaveIfError(clientThread.Open(aClientTid)); sl@0: sl@0: RProcess clientProcess; sl@0: CleanupClosePushL(clientProcess); sl@0: User::LeaveIfError(clientThread.Process(clientProcess)); sl@0: clientProcessId = clientProcess.Id(); sl@0: CleanupStack::PopAndDestroy(2, &clientThread); // clientProcess, clientThread sl@0: sl@0: RProcess thisProcess; sl@0: TBool secureDrmMode = clientProcessId != thisProcess.Id(); sl@0: thisProcess.Close(); sl@0: sl@0: CMMFControllerExtendedData* dataSet = new(ELeave) CMMFControllerExtendedData(); sl@0: CleanupStack::PushL(dataSet); sl@0: dataSet->SetClientThreadId(aClientTid); sl@0: dataSet->SetSecureDrmMode(secureDrmMode); sl@0: CleanupStack::Pop(dataSet); sl@0: sl@0: return dataSet; sl@0: } sl@0: sl@0: sl@0: EXPORT_C CMMFCustomCommandParserManager* CMMFCustomCommandParserManager::NewL() sl@0: { sl@0: return new(ELeave) CMMFCustomCommandParserManager; sl@0: } sl@0: sl@0: CMMFCustomCommandParserManager::CMMFCustomCommandParserManager() sl@0: { sl@0: } sl@0: sl@0: EXPORT_C CMMFCustomCommandParserManager::~CMMFCustomCommandParserManager() sl@0: { sl@0: iParsers.ResetAndDestroy(); sl@0: iParsers.Close(); sl@0: } sl@0: sl@0: EXPORT_C TBool CMMFCustomCommandParserManager::HandleRequest(TMMFMessage& aMessage) sl@0: { sl@0: TBool handledRequest = EFalse; sl@0: for (TInt i=0; iInterfaceId() == aMessage.Destination().InterfaceId()) sl@0: { sl@0: c->HandleRequest(aMessage); sl@0: handledRequest = ETrue; sl@0: break; sl@0: } sl@0: } sl@0: return handledRequest; sl@0: } sl@0: sl@0: EXPORT_C void CMMFCustomCommandParserManager::AddCustomCommandParserL(CMMFCustomCommandParserBase& aParser) sl@0: { sl@0: User::LeaveIfError(iParsers.Append(&aParser)); sl@0: } sl@0: sl@0: sl@0: TBool CMMFController::DoAddFileHandleDataSourceL(TMMFMessage& aMessage) sl@0: { sl@0: RFile file; sl@0: aMessage.AdoptFileHandleFromClientL(1,2, file); sl@0: CleanupClosePushL(file); sl@0: TMMFFileHandleConfig fileConfig; sl@0: fileConfig().iFile = &file; sl@0: // Create the source sl@0: MDataSource* source = MDataSource::NewSourceL(KUidMmfFileSource, fileConfig); sl@0: CleanupStack::PopAndDestroy(&file); sl@0: CleanupDeletePushL(source); sl@0: CMMFDataSourceHolder* holder = new(ELeave) CMMFDataSourceHolder(*source); sl@0: CleanupStack::Pop(source);//source (since now owned by holder) sl@0: sl@0: CleanupStack::PushL(holder); sl@0: // Append holder to array of MMFObjects sl@0: User::LeaveIfError(MMFObjectContainerL().AddMMFObject(*holder)); sl@0: CleanupStack::Pop(holder);//holder sl@0: sl@0: // Write source handle info back to client sl@0: TMMFMessageDestination handleInfo(holder->Handle()); sl@0: TMMFMessageDestinationPckg handlePckg(handleInfo); sl@0: TInt error = aMessage.WriteDataToClient(handlePckg); sl@0: sl@0: // Add source to plugin sl@0: if (!error) sl@0: TRAP(error, AddDataSourceL(*source)); sl@0: sl@0: if (error) sl@0: { sl@0: // Source not accepted by plugin or we couldn't write handle info back to client, sl@0: // so delete it and return error to client sl@0: MMFObjectContainerL().RemoveAndDestroyMMFObject(*holder); sl@0: User::Leave(error); sl@0: } sl@0: sl@0: return ETrue; sl@0: } sl@0: sl@0: sl@0: TBool CMMFController::DoAddFileHandleDataSinkL(TMMFMessage& aMessage) sl@0: { sl@0: RFile file; sl@0: aMessage.AdoptFileHandleFromClientL(1,2, file); sl@0: CleanupClosePushL(file); sl@0: TMMFFileHandleConfig fileConfig; sl@0: fileConfig().iFile = &file; sl@0: // Create the sink sl@0: MDataSink* sink = MDataSink::NewSinkL(KUidMmfFileSink, fileConfig); sl@0: CleanupStack::PopAndDestroy(&file); // close our handle to the file sl@0: CleanupDeletePushL(sink); sl@0: CMMFDataSinkHolder* holder = new(ELeave) CMMFDataSinkHolder(*sink); sl@0: CleanupStack::Pop(sink);//sink (since now owned by holder) sl@0: sl@0: CleanupStack::PushL(holder); sl@0: // Append sink to array sl@0: User::LeaveIfError(MMFObjectContainerL().AddMMFObject(*holder)); sl@0: CleanupStack::Pop(holder);//holder sl@0: sl@0: sl@0: // Write sink handle info back to client sl@0: TMMFMessageDestination handleInfo(holder->Handle()); sl@0: TMMFMessageDestinationPckg handlePckg(handleInfo); sl@0: TInt error = aMessage.WriteDataToClient(handlePckg); sl@0: sl@0: // Add sink to plugin sl@0: if (!error) sl@0: TRAP(error, AddDataSinkL(*sink)); sl@0: sl@0: if (error) sl@0: { sl@0: // Sink not accepted by plugin or we couldn't write handle info back to client, sl@0: // so delete it and return error to client sl@0: MMFObjectContainerL().RemoveAndDestroyMMFObject(*holder); sl@0: User::Leave(error); sl@0: } sl@0: sl@0: return ETrue; sl@0: } sl@0: sl@0: EXPORT_C TThreadId CMMFController::ClientThreadIdL() sl@0: { sl@0: return GetExtendedDataL()->ClientThreadId(); sl@0: } sl@0: sl@0: EXPORT_C TBool CMMFController::IsSecureDrmModeL() sl@0: { sl@0: return GetExtendedDataL()->SecureDrmMode(); sl@0: } sl@0: